diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/IcePatch2/Calc.cpp | 129 | ||||
-rw-r--r-- | cpp/src/IcePatch2/Util.cpp | 30 |
2 files changed, 130 insertions, 29 deletions
diff --git a/cpp/src/IcePatch2/Calc.cpp b/cpp/src/IcePatch2/Calc.cpp index 6114323a70f..cbf37260018 100644 --- a/cpp/src/IcePatch2/Calc.cpp +++ b/cpp/src/IcePatch2/Calc.cpp @@ -17,6 +17,24 @@ using namespace std; using namespace Ice; using namespace IcePatch2; +struct FileInfoPathEqual: public binary_function<const FileInfo&, const FileInfo&, bool> +{ + bool + operator()(const FileInfo& lhs, const FileInfo& rhs) + { + return lhs.path != rhs.path; + } +}; + +struct FileInfoPathLess: public binary_function<const FileInfo&, const FileInfo&, bool> +{ + bool + operator()(const FileInfo& lhs, const FileInfo& rhs) + { + return lhs.path < rhs.path; + } +}; + class CalcCB : public GetFileInfoSeqCB { public: @@ -46,7 +64,7 @@ public: void usage(const char* appName) { - cerr << "Usage: " << appName << " [options] DIR\n"; + cerr << "Usage: " << appName << " [options] DIR [FILES...]\n"; cerr << "Options:\n" "-h, --help Show this message.\n" @@ -61,7 +79,8 @@ int main(int argc, char* argv[]) { string dataDir; - int mode = 1; + StringSeq fileSeq; + int compress = 1; bool verbose = false; int i; @@ -79,11 +98,11 @@ main(int argc, char* argv[]) } else if(strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--compress") == 0) { - mode = 2; + compress = 2; } else if(strcmp(argv[i], "-Z") == 0 || strcmp(argv[i], "--no-compress") == 0) { - mode = 0; + compress = 0; } else if(strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--verbose") == 0) { @@ -103,9 +122,7 @@ main(int argc, char* argv[]) } else { - cerr << argv[0] << ": too many arguments" << endl; - usage(argv[0]); - return EXIT_FAILURE; + fileSeq.push_back(normalize(argv[i])); } } } @@ -119,36 +136,110 @@ main(int argc, char* argv[]) try { -#ifdef _WIN32 - if(dataDir[0] != '/' && !(dataDir.size() > 1 && isalpha(dataDir[0]) && dataDir[1] == ':')) { +#ifdef _WIN32 char cwd[_MAX_PATH]; if(_getcwd(cwd, _MAX_PATH) == NULL) { throw "cannot get the current directory:\n" + lastError(); } - dataDir = string(cwd) + '/' + dataDir; - } + if(dataDir[0] != '/' && !(dataDir.size() > 1 && isalpha(dataDir[0]) && dataDir[1] == ':')) + { + dataDir = string(cwd) + '/' + dataDir; + } + + for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p) + { + if((*p)[0] != '/' && !(p->size() > 1 && isalpha((*p)[0]) && (*p)[1] == ':')) + { + *p = string(cwd) + '/' + *p; + } + } #else - if(dataDir[0] != '/') - { char cwd[PATH_MAX]; if(getcwd(cwd, PATH_MAX) == NULL) { throw "cannot get the current directory:\n" + lastError(); } - dataDir = string(cwd) + '/' + dataDir; - } + if(dataDir[0] != '/') + { + dataDir = string(cwd) + '/' + dataDir; + } + + for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p) + { + if((*p)[0] != '/') + { + *p = string(cwd) + '/' + *p; + } + } #endif + } + + { + string dataDirWithSlash = dataDir + '/'; - FileInfoSeq infoSeq; + for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p) + { + if(p->compare(0, dataDirWithSlash.size(), dataDirWithSlash) != 0) + { + throw "`" + *p + "' is not a path in `" + dataDir + "'"; + } - CalcCB calcCB; - if(!getFileInfoSeq(dataDir, mode, verbose ? &calcCB : 0, infoSeq)) + p->erase(0, dataDirWithSlash.size()); + } + } + + FileInfoSeq infoSeq; + + if(fileSeq.empty()) { - return EXIT_FAILURE; + CalcCB calcCB; + if(!getFileInfoSeq(dataDir, compress, verbose ? &calcCB : 0, infoSeq)) + { + return EXIT_FAILURE; + } + } + else + { + loadFileInfoSeq(dataDir, infoSeq); + + for(StringSeq::const_iterator p = fileSeq.begin(); p != fileSeq.end(); ++p) + { + FileInfoSeq partialInfoSeq; + + CalcCB calcCB; + if(!getFileInfoSeqSubDir(dataDir, *p, compress, verbose ? &calcCB : 0, partialInfoSeq)) + { + return EXIT_FAILURE; + } + + FileInfoSeq newInfoSeq; + newInfoSeq.reserve(infoSeq.size()); + + set_difference(infoSeq.begin(), + infoSeq.end(), + partialInfoSeq.begin(), + partialInfoSeq.end(), + back_inserter(newInfoSeq), + FileInfoPathLess()); + + infoSeq.swap(newInfoSeq); + + newInfoSeq.clear(); + newInfoSeq.reserve(infoSeq.size() + partialInfoSeq.size()); + + set_union(infoSeq.begin(), + infoSeq.end(), + partialInfoSeq.begin(), + partialInfoSeq.end(), + back_inserter(newInfoSeq), + FileInfoPathLess()); + + infoSeq.swap(newInfoSeq); + } } saveFileInfoSeq(dataDir, infoSeq); diff --git a/cpp/src/IcePatch2/Util.cpp b/cpp/src/IcePatch2/Util.cpp index ca866606839..0bf6c71106c 100644 --- a/cpp/src/IcePatch2/Util.cpp +++ b/cpp/src/IcePatch2/Util.cpp @@ -653,7 +653,8 @@ IcePatch2::decompressFile(const string& pa) } static bool -getFileInfoSeqInt(const string& basePath, const string& relPath, int mode, GetFileInfoSeqCB* cb, FileInfoSeq& infoSeq) +getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, GetFileInfoSeqCB* cb, + FileInfoSeq& infoSeq) { const string path = basePath + '/' + relPath; @@ -734,7 +735,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int mode, GetFi StringSeq content = readDirectory(path); for(StringSeq::const_iterator p = content.begin(); p != content.end() ; ++p) { - if(!getFileInfoSeqInt(basePath, normalize(relPath + '/' + *p), mode, cb, infoSeq)) + if(!getFileInfoSeqInt(basePath, normalize(relPath + '/' + *p), compress, cb, infoSeq)) { return false; } @@ -770,16 +771,16 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int mode, GetFi close(fd); // - // mode == 0: Never compress. - // mode == 1: Compress if necessary. - // mode >= 2: Always compress. + // compress == 0: Never compress. + // compress == 1: Compress if necessary. + // compress >= 2: Always compress. // - if(mode > 0) + if(compress > 0) { string pathBZ2 = path + ".bz2"; struct stat bufBZ2; - if(mode >= 2 || stat(pathBZ2.c_str(), &bufBZ2) == -1 || buf.st_mtime >= bufBZ2.st_mtime) + if(compress >= 2 || stat(pathBZ2.c_str(), &bufBZ2) == -1 || buf.st_mtime >= bufBZ2.st_mtime) { if(cb && !cb->compress(relPath)) { @@ -823,11 +824,20 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int mode, GetFi } bool -IcePatch2::getFileInfoSeq(const string& pa, int mode, GetFileInfoSeqCB* cb, FileInfoSeq& infoSeq) +IcePatch2::getFileInfoSeq(const string& basePath, int compress, GetFileInfoSeqCB* cb, + FileInfoSeq& infoSeq) { - const string path = normalize(pa); + return getFileInfoSeqSubDir(basePath, ".", compress, cb, infoSeq); +} + +bool +IcePatch2::getFileInfoSeqSubDir(const string& basePa, const string& relPa, int compress, GetFileInfoSeqCB* cb, + FileInfoSeq& infoSeq) +{ + const string basePath = normalize(basePa); + const string relPath = normalize(relPa); - if(!getFileInfoSeqInt(path, ".", mode, cb, infoSeq)) + if(!getFileInfoSeqInt(basePath, relPath, compress, cb, infoSeq)) { return false; } |