summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNils Maier <maierman@web.de>2016-07-18 23:11:55 +0200
committerNils Maier <maierman@web.de>2016-07-19 20:55:41 +0200
commit665a1d1b3581dc0fc7076cf66be2fc8982ab7be2 (patch)
tree8e3d1f14518c021a31f6dd8068828ea9cb6553b9
parentb6d9e7a01fb7f82fb52448e2cf9f6f6c6c25f8ad (diff)
Better auto-renaming
Up until now aria2 file auto renaming worked by just appending a new unique number to the file path, behind the file name extension, if any, changing what most other programs consider the file extension in the process. Now, aria2 will attempt to insert the number before the file extension, leaving the extension intact, so that e.g. a ".jpg" still is a ".jpg" file and opens in your configured image viewer when clicking it. If a file has no extension (incl. so called "dot files"), the number will be appended to the file name as usual. Note: This is a potentially breaking change that might break third party scripts that rely on aria2 auto file renaming producing a certain format for renamed files. Please fix your scripts accordingly. Closes GH-709
-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(