summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/manual-src/en/aria2c.rst3
-rw-r--r--src/RequestGroup.cc22
-rw-r--r--src/RequestGroup.h4
-rw-r--r--test/RequestGroupTest.cc53
4 files changed, 78 insertions, 4 deletions
diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst
index 83182860..539b8e66 100644
--- a/doc/manual-src/en/aria2c.rst
+++ b/doc/manual-src/en/aria2c.rst
@@ -1175,7 +1175,8 @@ Advanced Options
Rename file name if the same file already exists.
This option works only in HTTP(S)/FTP download.
- The new file name has a dot and a number(1..9999) appended.
+ The new file name has a dot and a number(1..9999) appended after the
+ name, but before the file extension, if any.
Default: ``true``
.. option:: --auto-save-interval=<SEC>
diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc
index c89dacbf..748b6fd4 100644
--- a/src/RequestGroup.cc
+++ b/src/RequestGroup.cc
@@ -778,8 +778,28 @@ void RequestGroup::tryAutoFileRenaming()
fmt("File renaming failed: %s", getFirstFilePath().c_str()),
error_code::FILE_RENAMING_FAILED);
}
+ auto fn = filepath;
+ std::string ext;
+ const auto idx = fn.find_last_of(".");
+ const auto slash = fn.find_last_of("\\/");
+ // Do extract the extension, as in "file.ext" = "file" and ".ext",
+ // but do not consider ".file" to be a file name without extension instead
+ // of a blank file name and an extension of ".file"
+ if (idx != std::string::npos &&
+ // fn has no path component and starts with a dot, but has no extension
+ // otherwise
+ idx != 0 &&
+ // has a file path component if we found a slash.
+ // if slash == idx - 1 this means a form of "*/.*", so the file name
+ // starts with a dot, has no extension otherwise, and therefore do not
+ // extract an extension either
+ (slash == std::string::npos || slash < idx - 1)
+ ) {
+ ext = fn.substr(idx);
+ fn = fn.substr(0, idx);
+ }
for (int i = 1; i < 10000; ++i) {
- auto newfilename = fmt("%s.%d", filepath.c_str(), i);
+ auto newfilename = fmt("%s.%d%s", fn.c_str(), i, ext.c_str());
File newfile(newfilename);
File ctrlfile(newfile.getPath() + DefaultBtProgressInfoFile::getSuffix());
if (!newfile.exists() || (newfile.exists() && ctrlfile.exists())) {
diff --git a/src/RequestGroup.h b/src/RequestGroup.h
index 8b7862eb..6698f93d 100644
--- a/src/RequestGroup.h
+++ b/src/RequestGroup.h
@@ -199,8 +199,6 @@ private:
void initializePostDownloadHandler();
- void tryAutoFileRenaming();
-
// Returns the result code of this RequestGroup. If the download
// finished, then returns error_code::FINISHED. If the
// download didn't finish and error result is available in
@@ -219,6 +217,8 @@ public:
bool isCheckIntegrityReady();
+ void tryAutoFileRenaming();
+
const std::shared_ptr<SegmentMan>& getSegmentMan() const
{
return segmentMan_;
diff --git a/test/RequestGroupTest.cc b/test/RequestGroupTest.cc
index 47bc6e05..ddbb56c3 100644
--- a/test/RequestGroupTest.cc
+++ b/test/RequestGroupTest.cc
@@ -14,6 +14,7 @@ class RequestGroupTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(RequestGroupTest);
CPPUNIT_TEST(testGetFirstFilePath);
+ CPPUNIT_TEST(testTryAutoFileRenaming);
CPPUNIT_TEST(testCreateDownloadResult);
CPPUNIT_TEST_SUITE_END();
@@ -24,6 +25,7 @@ public:
void setUp() { option_.reset(new Option()); }
void testGetFirstFilePath();
+ void testTryAutoFileRenaming();
void testCreateDownloadResult();
};
@@ -44,6 +46,57 @@ void RequestGroupTest::testGetFirstFilePath()
CPPUNIT_ASSERT_EQUAL(std::string("[MEMORY]myfile"), group.getFirstFilePath());
}
+void RequestGroupTest::testTryAutoFileRenaming()
+{
+ std::shared_ptr<DownloadContext> ctx(
+ new DownloadContext(1_k, 1_k, "/tmp/myfile"));
+
+ RequestGroup group(GroupId::create(), option_);
+ group.setDownloadContext(ctx);
+
+ option_->put(PREF_AUTO_FILE_RENAMING, "false");
+ try {
+ group.tryAutoFileRenaming();
+ }
+ catch (const Exception& ex) {
+ CPPUNIT_ASSERT_EQUAL(error_code::FILE_ALREADY_EXISTS, ex.getErrorCode());
+
+ }
+
+ option_->put(PREF_AUTO_FILE_RENAMING, "true");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string("/tmp/myfile.1"), group.getFirstFilePath());
+
+ ctx->getFirstFileEntry()->setPath("/tmp/myfile.txt");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string("/tmp/myfile.1.txt"), group.getFirstFilePath());
+
+ ctx->getFirstFileEntry()->setPath("/tmp.txt/myfile");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string("/tmp.txt/myfile.1"), group.getFirstFilePath());
+
+ ctx->getFirstFileEntry()->setPath("/tmp.txt/myfile.txt");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string("/tmp.txt/myfile.1.txt"), group.getFirstFilePath());
+
+ ctx->getFirstFileEntry()->setPath(".bashrc");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string(".bashrc.1"), group.getFirstFilePath());
+
+ ctx->getFirstFileEntry()->setPath(".bashrc.txt");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string(".bashrc.1.txt"), group.getFirstFilePath());
+
+ ctx->getFirstFileEntry()->setPath("/tmp.txt/.bashrc");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string("/tmp.txt/.bashrc.1"), group.getFirstFilePath());
+
+ ctx->getFirstFileEntry()->setPath("/tmp.txt/.bashrc.txt");
+ group.tryAutoFileRenaming();
+ CPPUNIT_ASSERT_EQUAL(std::string("/tmp.txt/.bashrc.1.txt"), group.getFirstFilePath());
+
+}
+
void RequestGroupTest::testCreateDownloadResult()
{
std::shared_ptr<DownloadContext> ctx(