linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #06357
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3157: rename case-insensitive duplicated directories
------------------------------------------------------------
revno: 3157
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Mon 2012-12-17 18:07:08 +0100
message:
rename case-insensitive duplicated directories
modified:
dcpp/ShareManager.cpp
dcpp/ShareManager.h
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/ShareManager.cpp'
--- dcpp/ShareManager.cpp 2012-12-14 17:07:25 +0000
+++ dcpp/ShareManager.cpp 2012-12-17 17:07:08 +0000
@@ -85,6 +85,10 @@
{
}
+const string& ShareManager::Directory::getRealName() const noexcept {
+ return realName ? realName.get() : name;
+}
+
string ShareManager::Directory::getADCPath() const noexcept {
if(!getParent())
return '/' + name + '/';
@@ -107,9 +111,9 @@
string ShareManager::Directory::getRealPath(const std::string& path) const {
if(getParent()) {
- return getParent()->getRealPath(getName() + PATH_SEPARATOR_STR + path);
+ return getParent()->getRealPath(getRealName() + PATH_SEPARATOR_STR + path);
} else {
- return ShareManager::getInstance()->findRealRoot(getName(), path);
+ return ShareManager::getInstance()->findRealRoot(getRealName(), path);
}
}
@@ -288,12 +292,12 @@
throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
}
- auto dmi = getByVirtual( virtualPath.substr(1, i - 1));
+ auto dmi = directories.find(virtualPath.substr(1, i - 1));
if(dmi == directories.end()) {
throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
}
- auto d = *dmi;
+ auto d = dmi->second;
auto j = i + 1;
while((i = virtualPath.find('/', j)) != string::npos) {
@@ -336,7 +340,7 @@
bool ShareManager::hasVirtual(const string& virtualName) const noexcept {
Lock l(cs);
- return getByVirtual(virtualName) != directories.end();
+ return directories.find(virtualName) != directories.end();
}
void ShareManager::load(SimpleXML& aXml) {
@@ -358,8 +362,8 @@
const string& virtualName = aXml.getChildAttrib("Virtual");
string vName = validateVirtual(virtualName.empty() ? Util::getLastDir(realPath) : virtualName);
shares[move(realPath)] = vName;
- if(getByVirtual(vName) == directories.end()) {
- directories.push_back(Directory::create(vName));
+ if(directories.find(vName) == directories.end()) {
+ directories[vName] = Directory::create(vName);
}
}
aXml.stepOut();
@@ -373,17 +377,15 @@
static const string STTH = "TTH";
struct ShareLoader : public SimpleXMLReader::CallBack {
- ShareLoader(ShareManager::DirList& aDirs) : dirs(aDirs), cur(0), depth(0) { }
+ ShareLoader(decltype(ShareManager::directories)& aDirs) : dirs(aDirs), cur(0), depth(0) { }
void startTag(const string& name, StringPairList& attribs, bool simple) {
if(name == SDIRECTORY) {
const string& name = getAttrib(attribs, SNAME, 0);
if(!name.empty()) {
if(depth == 0) {
- for(auto& i: dirs) {
- if(Util::stricmp(i->getName(), name) == 0) {
- cur = i;
- break;
- }
+ auto i = dirs.find(name);
+ if(i != dirs.end()) {
+ cur = i->second;
}
} else if(cur) {
cur = ShareManager::Directory::create(name, cur);
@@ -419,7 +421,7 @@
}
private:
- ShareManager::DirList& dirs;
+ decltype(ShareManager::directories)& dirs;
ShareManager::Directory::Ptr cur;
size_t depth;
@@ -435,8 +437,8 @@
xml.parse(f);
- for(const auto& d: directories) {
- updateIndices(*d);
+ for(const auto& i: directories) {
+ updateIndices(*i.second);
}
return true;
@@ -487,7 +489,7 @@
HashManager::HashPauser pauser;
- Directory::Ptr dp = buildTree(realPath, Directory::Ptr());
+ auto dp = buildTree(realPath);
string vName = validateVirtual(virtualName);
dp->setName(vName);
@@ -503,17 +505,16 @@
}
ShareManager::Directory::Ptr ShareManager::merge(const Directory::Ptr& directory, const string& realPath) {
- for(auto& i: directories) {
- if(Util::stricmp(i->getName(), directory->getName()) == 0) {
- dcdebug("Merging directory <%s> into %s\n", realPath.c_str(), directory->getName().c_str());
- i->merge(directory, realPath);
- return i;
- }
+ auto i = directories.find(directory->getName());
+ if(i != directories.end()) {
+ dcdebug("Merging directory <%s> into %s\n", realPath.c_str(), directory->getName().c_str());
+ i->second->merge(directory, realPath);
+ return i->second;
}
dcdebug("Adding new directory %s\n", directory->getName().c_str());
- directories.push_back(directory);
+ directories[directory->getName()] = directory;
return directory;
}
@@ -570,7 +571,7 @@
vname = base + " (" + Util::toString(num) + ")" + ext;
} while(parent->nameInUse(vname));
dcdebug("Renaming duplicate <%s> to <%s>\n", name.c_str(), vname.c_str());
- realPath = sourcePath + name;
+ realPath = sourcePath + move(name);
name = move(vname);
} else {
realPath.reset();
@@ -591,13 +592,7 @@
}
auto vName = i->second;
- for(auto j = directories.begin(); j != directories.end(); ) {
- if(Util::stricmp((*j)->getName(), vName) == 0) {
- directories.erase(j++);
- } else {
- ++j;
- }
- }
+ directories.erase(vName);
shares.erase(i);
@@ -606,7 +601,7 @@
// Readd all directories with the same vName
for(i = shares.begin(); i != shares.end(); ++i) {
if(Util::stricmp(i->second, vName) == 0 && checkHidden(i->first)) {
- Directory::Ptr dp = buildTree(i->first, 0);
+ auto dp = buildTree(i->first);
dp->setName(i->second);
merge(dp, i->first);
}
@@ -621,24 +616,15 @@
addDirectory(realPath, virtualName);
}
-ShareManager::DirList::const_iterator ShareManager::getByVirtual(const string& virtualName) const noexcept {
- for(auto i = directories.begin(); i != directories.end(); ++i) {
- if(Util::stricmp((*i)->getName(), virtualName) == 0) {
- return i;
- }
- }
- return directories.end();
-}
-
int64_t ShareManager::getShareSize(const string& realPath) const noexcept {
Lock l(cs);
dcassert(realPath.size()>0);
auto i = shares.find(realPath);
if(i != shares.end()) {
- auto j = getByVirtual(i->second);
+ auto j = directories.find(i->second);
if(j != directories.end()) {
- return (*j)->getSize();
+ return j->second->getSize();
}
}
return -1;
@@ -658,27 +644,25 @@
return tthIndex.size();
}
-ShareManager::Directory::Ptr ShareManager::buildTree(const string& aName, const Directory::Ptr& aParent) {
- auto dir = Directory::create(Util::getLastDir(aName), aParent);
+ShareManager::Directory::Ptr ShareManager::buildTree(const string& realPath, optional<const string&> dirName, const Directory::Ptr& parent) {
+ auto dir = Directory::create(dirName ? dirName.get() : Util::getLastDir(realPath), parent);
auto lastFileIter = dir->files.begin();
- FileFindIter end;
#ifdef _WIN32
- for(FileFindIter i(aName + "*"); i != end; ++i) {
+ for(FileFindIter i(realPath + "*"), end; i != end; ++i) {
#else
//the fileiter just searches directorys for now, not sure if more
//will be needed later
- //for(FileFindIter i(aName + "*"); i != end; ++i) {
- for(FileFindIter i(aName); i != end; ++i) {
+ for(FileFindIter i(realPath), end; i != end; ++i) {
#endif
- string name = i->getFileName();
+ auto name = i->getFileName();
if(name.empty()) {
- LogManager::getInstance()->message(str(F_("Invalid file name found while hashing folder %1%") % Util::addBrackets(aName)));
+ LogManager::getInstance()->message(str(F_("Invalid file name found while hashing folder %1%") % Util::addBrackets(realPath)));
continue;
}
-
+
if(name == "." || name == "..")
continue;
if(!SETTING(SHARE_HIDDEN) && i->isHidden())
@@ -687,24 +671,39 @@
continue;
if(i->isDirectory()) {
- string newName = aName + name + PATH_SEPARATOR;
- if(Util::stricmp(newName, SETTING(TEMP_DOWNLOAD_DIRECTORY)) != 0) {
- dir->directories[name] = buildTree(newName, dir);
- }
+ auto newRealPath = realPath + name + PATH_SEPARATOR;
+
+ // don't share unfinished downloads
+ if(newRealPath == SETTING(TEMP_DOWNLOAD_DIRECTORY)) { continue; }
+
+ auto virtualName = name;
+ if(dir->nameInUse(virtualName)) {
+ uint32_t num = 0;
+ do {
+ ++num;
+ virtualName = name + " (" + Util::toString(num) + ")";
+ } while(dir->nameInUse(virtualName));
+ }
+
+ dir->directories[virtualName] = buildTree(newRealPath, virtualName, dir);
+
+ if(virtualName != name) {
+ dir->directories[virtualName]->setRealName(move(name));
+ }
+
} else {
// Not a directory, assume it's a file...make sure we're not sharing the settings file...
- if(Util::stricmp(name.c_str(), "DCPlusPlus.xml") == 0 ||
- Util::stricmp(name.c_str(), "Favorites.xml") == 0) { continue; }
+ if(name == "DCPlusPlus.xml" || name == "Favorites.xml") { continue; }
- int64_t size = i->getSize();
- string fileName = aName + name;
+ auto size = i->getSize();
+ auto fileName = realPath + name;
// don't share the private key file
- if(Util::stricmp(fileName, SETTING(TLS_PRIVATE_KEY_FILE)) == 0) { continue; }
+ if(fileName == SETTING(TLS_PRIVATE_KEY_FILE)) { continue; }
Directory::File f(name, size, dir,
HashManager::getInstance()->getTTH(fileName, size, i->getLastWriteTime()));
- f.validateName(aName);
+ f.validateName(realPath);
lastFileIter = dir->files.insert(lastFileIter, move(f));
}
}
@@ -712,8 +711,8 @@
return dir;
}
-bool ShareManager::checkHidden(const string& aName) const {
- FileFindIter ff = FileFindIter(aName.substr(0, aName.size() - 1));
+bool ShareManager::checkHidden(const string& realPath) const {
+ FileFindIter ff = FileFindIter(realPath.substr(0, realPath.size() - 1));
if (ff != FileFindIter()) {
return (SETTING(SHARE_HIDDEN) || !ff->isHidden());
@@ -741,11 +740,11 @@
bloom.clear();
for(auto& i: directories) {
- updateIndices(*i);
+ updateIndices(*i.second);
}
}
-void ShareManager::updateIndices(Directory& dir, const Directory::File::Set::iterator& i) {
+void ShareManager::updateIndices(Directory& dir, const decltype(std::declval<Directory>().files.begin())& i) {
const Directory::File& f = *i;
if(!f.tth) {
@@ -826,7 +825,7 @@
vector<pair<Directory::Ptr, string>> newDirs;
for(auto& i: dirs) {
if (checkHidden(i.second)) {
- Directory::Ptr dp = buildTree(i.second, Directory::Ptr());
+ auto dp = buildTree(i.second);
dp->setName(i.first);
newDirs.emplace_back(dp, i.second);
}
@@ -888,7 +887,7 @@
newXmlFile.write(SimpleXML::utf8Header);
newXmlFile.write("<FileListing Version=\"1\" CID=\"" + ClientManager::getInstance()->getMe()->getCID().toBase32() + "\" Base=\"/\" Generator=\"" APPNAME " " VERSIONSTRING "\">\r\n");
for(auto& i: directories) {
- i->toXml(newXmlFile, indent, tmp2, -1);
+ i.second->toXml(newXmlFile, indent, tmp2, -1);
}
newXmlFile.write("</FileListing>");
newXmlFile.flush();
@@ -941,7 +940,7 @@
if(dir == "/") {
for(auto& i: directories) {
tmp.clear();
- i->toXml(sos, indent, tmp, recurse ? -1 : 0);
+ i.second->toXml(sos, indent, tmp, recurse ? -1 : 0);
}
} else {
string::size_type i = 1, j = 1;
@@ -957,11 +956,10 @@
if(first) {
first = false;
- auto it = getByVirtual(dir.substr(j, i-j));
-
+ auto it = directories.find(dir.substr(j, i-j));
if(it == directories.end())
return 0;
- root = *it;
+ root = it->second;
} else {
auto it2 = root->directories.find(dir.substr(j, i-j));
@@ -1254,7 +1252,7 @@
return;
for(auto j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) {
- (*j)->search(results, ssl, aSearchType, aSize, aFileType, aClient, maxResults);
+ j->second->search(results, ssl, aSearchType, aSize, aFileType, aClient, maxResults);
}
}
@@ -1410,37 +1408,42 @@
}
for(auto j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) {
- (*j)->search(results, srch, maxResults);
+ j->second->search(results, srch, maxResults);
}
}
ShareManager::Directory::Ptr ShareManager::getDirectory(const string& realPath) noexcept {
for(auto& mi: shares) {
if(Util::strnicmp(realPath, mi.first, mi.first.length()) == 0) {
- Directory::Ptr d;
- for(auto& i: directories) {
- if(Util::stricmp(i->getName(), mi.second) == 0) {
- d = i;
- }
- }
-
- if(!d) {
- return Directory::Ptr();
- }
+ auto di = directories.find(mi.second);
+ if(di == directories.end()) {
+ return nullptr;
+ }
+ auto d = di->second;
string::size_type i;
string::size_type j = mi.first.length();
- while( (i = realPath.find(PATH_SEPARATOR, j)) != string::npos) {
- auto dmi = d->directories.find(realPath.substr(j, i-j));
+ while((i = realPath.find(PATH_SEPARATOR, j)) != string::npos) {
+ auto dirName = realPath.substr(j, i - j);
+
+ auto& subDirs = d->directories;
+ d.reset();
+ for(auto& subDir: subDirs) {
+ if(subDir.second->getRealName() == dirName) {
+ d = subDir.second;
+ break;
+ }
+ }
+ if(!d) {
+ return nullptr;
+ }
+
j = i + 1;
- if(dmi == d->directories.end())
- return Directory::Ptr();
- d = dmi->second;
}
return d;
}
}
- return Directory::Ptr();
+ return nullptr;
}
optional<const ShareManager::Directory::File&> ShareManager::getFile(const string& realPath, Directory::Ptr d) noexcept {
=== modified file 'dcpp/ShareManager.h'
--- dcpp/ShareManager.h 2012-12-13 17:50:01 +0000
+++ dcpp/ShareManager.h 2012-12-17 17:07:08 +0000
@@ -19,7 +19,6 @@
#ifndef DCPLUSPLUS_DCPP_SHARE_MANAGER_H
#define DCPLUSPLUS_DCPP_SHARE_MANAGER_H
-#include <list>
#include <map>
#include <memory>
#include <set>
@@ -130,10 +129,16 @@
class Directory : public FastAlloc<Directory>, public intrusive_ptr_base<Directory>, boost::noncopyable {
public:
typedef boost::intrusive_ptr<Directory> Ptr;
- typedef unordered_map<string, Ptr, noCaseStringHash, noCaseStringEq> Map;
- typedef Map::iterator MapIter;
struct File {
+ File() : size(0), parent(0) { }
+ File(const string& aName, int64_t aSize, const Directory::Ptr& aParent, const optional<TTHValue>& aRoot) :
+ name(aName), tth(aRoot), size(aSize), parent(aParent.get()) { }
+
+ bool operator==(const File& rhs) const {
+ return getParent() == rhs.getParent() && (Util::stricmp(getName(), rhs.getName()) == 0);
+ }
+
struct StringComp {
StringComp(const string& s) : a(s) { }
bool operator()(const File& b) const { return Util::stricmp(a, b.getName()) == 0; }
@@ -142,15 +147,6 @@
struct FileLess {
bool operator()(const File& a, const File& b) const { return (Util::stricmp(a.getName(), b.getName()) < 0); }
};
- typedef set<File, FileLess> Set;
-
- File() : size(0), parent(0) { }
- File(const string& aName, int64_t aSize, const Directory::Ptr& aParent, const optional<TTHValue>& aRoot) :
- name(aName), tth(aRoot), size(aSize), parent(aParent.get()) { }
-
- bool operator==(const File& rhs) const {
- return getParent() == rhs.getParent() && (Util::stricmp(getName(), rhs.getName()) == 0);
- }
/** Ensure this file's name doesn't clash with the names of the parent directory's sub-
directories or files; rename to "file (N).ext" otherwise (and set realPath to the
@@ -170,8 +166,8 @@
};
int64_t size;
- Map directories;
- File::Set files;
+ unordered_map<string, Ptr, noCaseStringHash, noCaseStringEq> directories;
+ set<File, File::FileLess> files;
static Ptr create(const string& aName, const Ptr& aParent = Ptr()) { return Ptr(new Directory(aName, aParent)); }
@@ -180,6 +176,9 @@
}
void addType(uint32_t type) noexcept;
+ const string& getRealName() const noexcept;
+ template<typename SetT> void setRealName(SetT&& realName) noexcept { this->realName = std::forward<SetT>(realName); }
+
string getADCPath() const noexcept;
string getFullName() const noexcept;
string getRealPath(const std::string& path) const;
@@ -197,21 +196,23 @@
void toXml(OutputStream& xmlFile, string& indent, string& tmp2, int8_t level) const;
void filesToXml(OutputStream& xmlFile, string& indent, string& tmp2) const;
- File::Set::const_iterator findFile(const string& aFile) const { return find_if(files.begin(), files.end(), Directory::File::StringComp(aFile)); }
+ auto findFile(const string& aFile) const -> decltype(files.cbegin()) { return find_if(files.begin(), files.end(), File::StringComp(aFile)); }
void merge(const Ptr& source, const string& realPath);
GETSET(string, name, Name);
GETSET(Directory*, parent, Parent);
+
private:
friend void intrusive_ptr_release(intrusive_ptr_base<Directory>*);
Directory(const string& aName, const Ptr& aParent);
~Directory() { }
+ optional<string> realName; // only defined if this directory had to be renamed to avoid duplication.
+
/** Set of flags that say which SearchManager::TYPE_* a directory contains */
uint32_t fileTypes;
-
};
friend class Directory;
@@ -264,8 +265,7 @@
mutable CriticalSection cs;
// List of root directory items
- typedef std::list<Directory::Ptr> DirList;
- DirList directories;
+ unordered_map<string, Directory::Ptr, noCaseStringHash, noCaseStringEq> directories;
/** Map real name to virtual name - multiple real names may be mapped to a single virtual one.
The map is sorted to make sure conflicts are always resolved in the same order when merging. */
@@ -277,19 +277,18 @@
const Directory::File& findFile(const string& virtualFile) const;
- Directory::Ptr buildTree(const string& aName, const Directory::Ptr& aParent);
- bool checkHidden(const string& aName) const;
+ Directory::Ptr buildTree(const string& realPath, optional<const string&> dirName = nullptr, const Directory::Ptr& parent = nullptr);
+ bool checkHidden(const string& realPath) const;
void rebuildIndices();
void updateIndices(Directory& aDirectory);
- void updateIndices(Directory& dir, const Directory::File::Set::iterator& i);
+ void updateIndices(Directory& dir, const decltype(std::declval<Directory>().files.begin())& i);
Directory::Ptr merge(const Directory::Ptr& directory, const string& realPath);
void generateXmlList();
bool loadCache() noexcept;
- DirList::const_iterator getByVirtual(const string& virtualName) const noexcept;
pair<Directory::Ptr, string> splitVirtual(const string& virtualPath) const;
string findRealRoot(const string& virtualRoot, const string& virtualLeaf) const;