improve duplicate file detection in torrent files

This commit is contained in:
Arvid Norberg 2013-11-18 06:59:47 +00:00
parent 31ecd1b914
commit bcb703b9a3
5 changed files with 35 additions and 8 deletions

View File

@ -133,6 +133,7 @@ namespace libtorrent
TORRENT_EXTRA_EXPORT std::string split_path(std::string const& f);
TORRENT_EXTRA_EXPORT char const* next_path_element(char const* p);
TORRENT_EXTRA_EXPORT std::string extension(std::string const& f);
TORRENT_EXTRA_EXPORT std::string remove_extension(std::string const& f);
TORRENT_EXTRA_EXPORT void replace_extension(std::string& f, std::string const& ext);
TORRENT_EXTRA_EXPORT bool is_root_path(std::string const& f);

View File

@ -423,6 +423,18 @@ namespace libtorrent
return "";
}
std::string remove_extension(std::string const& f)
{
char const* slash = strrchr(f.c_str(), '/');
#ifdef TORRENT_WINDOWS
slash = (std::max)((char const*)strrchr(f.c_str(), '\\'), slash);
#endif
char const* ext = strrchr(f.c_str(), '.');
// if we don't have an extension, just return f
if (ext == 0 || ext == &f[0] || (slash != NULL && ext < slash)) return f;
return f.substr(0, ext - &f[0]);
}
void replace_extension(std::string& f, std::string const& ext)
{
for (int i = f.size() - 1; i >= 0; --i)

View File

@ -402,12 +402,17 @@ namespace libtorrent
// as long as this file already exists
// increase the counter
int cnt = 0;
while (!files.insert(e.path).second)
if (!files.insert(e.path).second)
{
++cnt;
char suffix[50];
snprintf(suffix, sizeof(suffix), "%d%s", cnt, extension(e.path).c_str());
replace_extension(e.path, suffix);
std::string base = remove_extension(e.path);
std::string ext = extension(e.path);
do
{
++cnt;
char new_ext[50];
snprintf(new_ext, sizeof(new_ext), ".%d%s", cnt, ext.c_str());
e.path = base + new_ext;
} while (!files.insert(e.path).second);
}
target.add_file(e, file_hash ? file_hash->string_ptr() + info_ptr_diff : 0);

View File

@ -127,6 +127,11 @@ int test_main()
TEST_EQUAL(extension("blah.foo."), ".");
TEST_EQUAL(extension("blah.foo/bar"), "");
TEST_EQUAL(remove_extension("blah"), "blah");
TEST_EQUAL(remove_extension("blah.exe"), "blah");
TEST_EQUAL(remove_extension("blah.foo.bar"), "blah.foo");
TEST_EQUAL(remove_extension("blah.foo."), "blah.foo");
TEST_EQUAL(filename("blah"), "blah");
TEST_EQUAL(filename("/blah/foo/bar"), "bar");
TEST_EQUAL(filename("/blah/foo/bar/"), "bar");

View File

@ -41,7 +41,6 @@ int test_main()
{
file_storage fs;
int total_size = 100 * 0x4000;
fs.add_file("test/temporary.txt", 0x4000);
fs.add_file("test/A/tmp", 0x4000);
@ -76,12 +75,17 @@ int test_main()
"test/A/tmp",
"test/Temporary.1.txt", // duplicate of temporary.txt
"test/TeMPorArY.2.txT", // duplicate of temporary.txt
"test/a.1", // a file may not have the same name as a directory
// a file may not have the same name as a directory
// however, detecting this is not supported currently.
// it is in the next major release
"test/a",
"test/b.exe",
"test/B.1.ExE", // duplicate of b.exe
"test/B.2.exe", // duplicate of b.exe
"test/test/TEMPORARY.TXT", // a file with the same name in a seprate directory is fine
"test/A.2", // duplicate of directory a
"test/A.1", // duplicate of directory a
};
for (int i = 0; i < ti.num_files(); ++i)