diff options
Diffstat (limited to 'cpp/src')
-rwxr-xr-x | cpp/src/IcePatch2/ClientUtil.cpp | 132 | ||||
-rw-r--r-- | cpp/src/IcePatch2/Util.cpp | 32 |
2 files changed, 149 insertions, 15 deletions
diff --git a/cpp/src/IcePatch2/ClientUtil.cpp b/cpp/src/IcePatch2/ClientUtil.cpp index 220a03a4056..a01f70a16e6 100755 --- a/cpp/src/IcePatch2/ClientUtil.cpp +++ b/cpp/src/IcePatch2/ClientUtil.cpp @@ -47,7 +47,7 @@ public: } void - add(const FileInfo info) + add(const FileInfo& info) { IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); if(!_exception.empty()) @@ -115,6 +115,7 @@ public: try { decompressFile(_dataDir + '/' + info.path); + setFileFlags(_dataDir + '/' + info.path, info); remove(_dataDir + '/' + info.path + ".bz2"); } catch(const string& ex) @@ -370,26 +371,59 @@ IcePatch2::Patcher::prepare() if(node0Nxt < 256) { - _serverNoCompress->getFileInfoSeq_async(nxtCB, node0Nxt); + _serverCompress->getFileInfoSeq_async(nxtCB, node0Nxt); } FileInfoSeq files = curCB->getFileInfoSeq(); - sort(files.begin(), files.end(), FileInfoLess()); + sort(files.begin(), files.end(), FileInfoLess()); files.erase(unique(files.begin(), files.end(), FileInfoEqual()), files.end()); - + + // + // Compute the set of files which were removed. + // set_difference(tree0.nodes[node0].files.begin(), tree0.nodes[node0].files.end(), files.begin(), files.end(), back_inserter(_removeFiles), + FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here. + + // + // Compute the set of files which were updated (either the file contents, flags or both). + // + FileInfoSeq updatedFiles; + updatedFiles.reserve(files.size()); + + set_difference(files.begin(), + files.end(), + tree0.nodes[node0].files.begin(), + tree0.nodes[node0].files.end(), + back_inserter(updatedFiles), FileInfoLess()); - + + // + // Compute the set of files whose contents was updated. + // + FileInfoSeq contentsUpdatedFiles; + contentsUpdatedFiles.reserve(files.size()); + set_difference(files.begin(), files.end(), tree0.nodes[node0].files.begin(), tree0.nodes[node0].files.end(), - back_inserter(_updateFiles), + back_inserter(contentsUpdatedFiles), + FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here. + copy(contentsUpdatedFiles.begin(), contentsUpdatedFiles.end(), back_inserter(_updateFiles)); + + // + // Compute the set of files whose flags were updated. + // + set_difference(updatedFiles.begin(), + updatedFiles.end(), + contentsUpdatedFiles.begin(), + contentsUpdatedFiles.end(), + back_inserter(_updateFlags), FileInfoLess()); } @@ -403,11 +437,12 @@ IcePatch2::Patcher::prepare() { return false; } - } - + } + sort(_removeFiles.begin(), _removeFiles.end(), FileInfoLess()); sort(_updateFiles.begin(), _updateFiles.end(), FileInfoLess()); - + sort(_updateFlags.begin(), _updateFlags.end(), FileInfoLess()); + string pathLog = simplify(_dataDir + '/' + logFile); _log.open(pathLog.c_str()); if(!_log) @@ -440,6 +475,14 @@ IcePatch2::Patcher::patch(const string& d) return false; } } + + if(!_updateFlags.empty()) + { + if(!updateFlags(_updateFlags)) + { + return false; + } + } return true; } @@ -475,6 +518,19 @@ IcePatch2::Patcher::patch(const string& d) } } + FileInfoSeq updateFlag; + for(p = _updateFlags.begin(); p != _updateFlags.end(); ++p) + { + if(p->path == dir) + { + updateFlag.push_back(*p); + } + else if(p->path.compare(0, dirWithSlash.size(), dirWithSlash) == 0) + { + updateFlag.push_back(*p); + } + } + if(!remove.empty()) { if(!removeFiles(remove)) @@ -491,6 +547,14 @@ IcePatch2::Patcher::patch(const string& d) } } + if(!updateFlag.empty()) + { + if(!updateFlags(updateFlag)) + { + return false; + } + } + return true; } } @@ -862,3 +926,53 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre return true; } + +bool +IcePatch2::Patcher::updateFlags(const FileInfoSeq& files) +{ + for(FileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p) + { + if(p->size >= 0) // Regular file? + { + setFileFlags(_dataDir + '/' + p->path, *p); + } + } + + // + // Remove the old files whose flags were updated from the set of + // local files. + // + FileInfoSeq localFiles; + localFiles.reserve(_localFiles.size()); + set_difference(_localFiles.begin(), + _localFiles.end(), + files.begin(), + files.end(), + back_inserter(localFiles), + FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags. + + // + // Add the new files to the set of local file. + // + _localFiles.clear(); + set_union(localFiles.begin(), + localFiles.end(), + files.begin(), + files.end(), + back_inserter(_localFiles), + FileInfoLess()); + + FileInfoSeq newUpdateFlags; + + set_difference(_updateFlags.begin(), + _updateFlags.end(), + files.begin(), + files.end(), + back_inserter(newUpdateFlags), + FileInfoLess()); + + _updateFlags.swap(newUpdateFlags); + + return true; +} + diff --git a/cpp/src/IcePatch2/Util.cpp b/cpp/src/IcePatch2/Util.cpp index 9d293a11f4a..71af38368ae 100644 --- a/cpp/src/IcePatch2/Util.cpp +++ b/cpp/src/IcePatch2/Util.cpp @@ -712,6 +712,18 @@ IcePatch2::decompressFile(const string& pa) } fclose(stdioFileBZ2); +}; + +void +IcePatch2::setFileFlags(const string& pa, const FileInfo& info) +{ + const string path = simplify(pa); + struct stat buf; + if(stat(path.c_str(), &buf) == -1) + { + throw "cannot stat `" + path + "':\n" + lastError(); + } + chmod(path.c_str(), info.executable ? buf.st_mode | S_IXUSR : buf.st_mode & ~S_IXUSR); } static bool @@ -781,6 +793,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G FileInfo info; info.path = relPath; info.size = -1; + info.executable = false; ByteSeq bytes(relPath.size()); copy(relPath.begin(), relPath.end(), bytes.begin()); @@ -813,6 +826,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G FileInfo info; info.path = relPath; info.size = 0; + info.executable = buf.st_mode & S_IXUSR; ByteSeq bytes(relPath.size() + buf.st_size); copy(relPath.begin(), relPath.end(), bytes.begin()); @@ -1076,12 +1090,13 @@ IcePatch2::getFileTree0(const FileInfoSeq& infoSeq, FileTree0& tree0) } ByteSeq allChecksums1; - allChecksums1.resize(tree1.files.size() * 20); + allChecksums1.resize(tree1.files.size() * 21); // 20 bytes for the checksum + 1 byte for the flag ByteSeq::iterator c1 = allChecksums1.begin(); - - for(p = tree1.files.begin(); p != tree1.files.end(); ++p, c1 += 20) + + for(p = tree1.files.begin(); p != tree1.files.end(); ++p, c1 += 21) { copy(p->checksum.begin(), p->checksum.end(), c1); + *(c1 + 20) = p->executable; } if(!allChecksums1.empty()) @@ -1111,7 +1126,10 @@ IcePatch2::getFileTree0(const FileInfoSeq& infoSeq, FileTree0& tree0) ostream& IcePatch2::operator<<(ostream& os, const FileInfo& info) { - os << IceUtil::escapeString(info.path, "") << '\t' << bytesToString(info.checksum) << '\t' << info.size; + os << IceUtil::escapeString(info.path, "") << '\t' + << bytesToString(info.checksum) << '\t' + << info.size << '\t' + << info.executable; return os; } @@ -1126,8 +1144,10 @@ IcePatch2::operator>>(istream& is, FileInfo& info) getline(is, s, '\t'); info.checksum = stringToBytes(s); - getline(is, s, '\n'); - info.size = atoi(s.c_str()); + is >> info.size; + is >> info.executable; + + getline(is, s); // Read until the EOL return is; } |