mirror of https://github.com/aria2/aria2
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-709pull/709/merge
parent
b6d9e7a01f
commit
665a1d1b35
|
@ -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>
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue