// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/> // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //----------------------------------------------------------------------------- // includes //----------------------------------------------------------------------------- #include "stdpch.h" #include "nel/misc/path.h" #include "nel/misc/sha1.h" #include "bnp_patch.h" #define PERSISTENT_TOKEN_FAMILY RyzomTokenFamily //----------------------------------------------------------------------------- // Handy utility routines //----------------------------------------------------------------------------- void normaliseBnpFileName(std::string& fileName) { BOMB_IF(fileName.empty(),"Can't normalise an empty bnp file name",return); if (NLMISC::CFile::getExtension(fileName).empty() && fileName[fileName.size()-1]!='.') fileName+=".bnp"; } void applyDate (const std::string &sFilename, uint32 nDate) { // change the file time if(nDate != 0) { // _utimbuf utb; // utb.actime = utb.modtime = nDate; NLMISC::CFile::setRWAccess(sFilename); NLMISC::CFile::setFileModificationDate(sFilename, nDate); // _utime (sFilename.c_str (), &utb); } } //----------------------------------------------------------------------------- // class CBNPFileVersion //----------------------------------------------------------------------------- CBNPFileVersion::CBNPFileVersion() { _FileTime= 0; _FileSize= 0; _7ZFileSize=0; _PatchSize= 0; _VersionNumber= ~0u; } // setup record contents from a file name and version number // returns false if the file didn't exist bool CBNPFileVersion::setup(const std::string &fileName, uint32 versionNumber) { // make sure the file exists... BOMB_IF(!NLMISC::CFile::fileExists(fileName),("File not found: "+fileName).c_str(),return false); // generate a hash key for the file and store it in a vector of uint32 CHashKey hashKey= getSHA1(fileName); nlassert(hashKey.HashKeyString.size()==20); _HashKey.clear(); for (uint32 i=0;i<5;++i) _HashKey.push_back(*(uint32*)&hashKey.HashKeyString[4*i]); // get the other file properties _FileTime= NLMISC::CFile::getFileModificationDate(fileName); _FileSize= NLMISC::CFile::getFileSize(fileName); // setup the version number _VersionNumber= versionNumber; return true; } void CBNPFileVersion::setVersionNumber(uint32 nVersionNumber) { _VersionNumber = nVersionNumber; } void CBNPFileVersion::set7ZipFileSize(uint32 n7ZFileSize) { _7ZFileSize = n7ZFileSize; } void CBNPFileVersion::setPatchSize(uint32 nPatchSize) { _PatchSize = nPatchSize; } void CBNPFileVersion::setTimeStamp(uint32 nTimeStamp) { _FileTime = nTimeStamp; } // accessors uint32 CBNPFileVersion::getVersionNumber() const { return _VersionNumber; } uint32 CBNPFileVersion::getTimeStamp() const { return _FileTime; } uint32 CBNPFileVersion::getFileSize() const { return _FileSize; } uint32 CBNPFileVersion::get7ZFileSize() const { return _7ZFileSize; } uint32 CBNPFileVersion::getPatchSize() const { return _PatchSize; } CHashKey CBNPFileVersion::getHashKey() const { nlassert(_HashKey.size()==5); CHashKey hashKey; for (uint32 i=0;i<5;++i) { *(uint32*)&hashKey.HashKeyString[4*i]=_HashKey[i]; } return hashKey; } // == operator bool CBNPFileVersion::operator==(const CBNPFileVersion& other) const { // make sure the file sizes match if (_FileSize!=other._FileSize) return false; // make sure the hash keys match if (_HashKey!=other._HashKey) return false; // we don't compare version numbers or file dates as they're not interesting return true; } // != operator bool CBNPFileVersion::operator!=(const CBNPFileVersion& other) const { return !operator==(other); } //----------------------------------------------------------------------------- // Persistent data for CBNPFileVersion //----------------------------------------------------------------------------- #define PERSISTENT_CLASS CBNPFileVersion #define PERSISTENT_DATA \ PROP(uint32,_VersionNumber) \ PROP(uint32,_FileSize) \ PROP(uint32,_7ZFileSize) \ PROP(uint32,_FileTime) \ PROP(uint32,_PatchSize) \ PROP_VECT(uint32,_HashKey) //# pragma message( PERSISTENT_GENERATION_MESSAGE ) #include "persistent_data_template.h" #undef PERSISTENT_CLASS #undef PERSISTENT_DATA //----------------------------------------------------------------------------- // class CBNPFile //----------------------------------------------------------------------------- CBNPFile::CBNPFile() { _IsIncremental= true; } bool CBNPFile::addVersion(const std::string& bnpDirectory, const std::string& /* refDirectory */, IVersionNumberGenerator& version) { nlinfo("Checking need to add new version to file: %s",_FileName.c_str()); // perform a quick check to see if the time stamp and file size of the new BNP file match the last version in the index std::string fullFileName= bnpDirectory+_FileName; if (!NLMISC::CFile::fileExists(fullFileName)) return false; if (!_Versions.empty()) { if ((NLMISC::CFile::getFileSize(fullFileName)==(uint32)_Versions.back().getFileSize()) && (NLMISC::CFile::getFileModificationDate(fullFileName)==(uint32)_Versions.back().getTimeStamp())) return true; NLMISC::InfoLog->displayNL("File: %s\n size(%d != %d) || time(%d != %d)", fullFileName.c_str(), NLMISC::CFile::getFileSize(fullFileName), (uint32)_Versions.back().getFileSize(), NLMISC::CFile::getFileModificationDate(fullFileName), (uint32)_Versions.back().getTimeStamp() ); } // create a new record for the BNP file that we have on the disk at the moment // if no file was found then give up (return) CBNPFileVersion fileVersion; bool result= fileVersion.setup(fullFileName,~0u); if (result==false) return false; // compare the fileVersion record to the last record in the history. // If they don't match then append it if (_Versions.empty() || _Versions.back()!=fileVersion) { // if we haven't yet generated the version number for this version then go for it now version.grabVersionNumber(); fileVersion.setVersionNumber(version.getPackageVersionNumber()); // make sure that our version numbers are ever increasing... it would be fatal to have an out-of-order version if (!_Versions.empty()) nlassert(_Versions.back().getVersionNumber()<version.getPackageVersionNumber()); // the file's current checksum doesn't match the previous checksum so add the new version nlinfo("- Adding version %05u to file: %s",version.getPackageVersionNumber(),_FileName.c_str()); _Versions.push_back(fileVersion); // copy the file to create a new reference file... // NLMISC::CSString refFileName= NLMISC::CSString(refDirectory+_FileName).replace(".",NLMISC::toString("_%05u.",version.getPackageVersionNumber()).c_str()); // NLMISC::CFile::copyFile(refFileName, fullFileName); } else { // the file's size & current checksum match the previous version so just fix the file's timestamp nlinfo("Files contents matches previous version but time stamp is different: %s",fullFileName.c_str()); applyDate(fullFileName,_Versions.back().getTimeStamp()); } // if we're flagged as non-incremental then we don't need a version history if (!_IsIncremental && _Versions.size()>1) { _Versions[0]= _Versions.back(); _Versions.resize(1); } return true; } uint32 CBNPFile::getLatestVersionNumber(uint32 max) const { if (_Versions.empty()) return 0; uint32 i=0; for (i=(uint32)_Versions.size();i--;) if (_Versions[i].getVersionNumber()<=max) return _Versions[i].getVersionNumber(); nlinfo("File %s didn't exist before version %d",_FileName.c_str(),max); return 0; } uint32 CBNPFile::versionCount() const { return (uint32)_Versions.size(); } const CBNPFileVersion& CBNPFile::getVersion(uint32 idx) const { nlassert(idx<versionCount()); return _Versions[idx]; } CBNPFileVersion& CBNPFile::getVersion(uint32 idx) { nlassert(idx<versionCount()); return _Versions[idx]; } void CBNPFile::setFileName(const std::string& fileName) { _FileName= fileName; } const std::string& CBNPFile::getFileName() const { return _FileName; } void CBNPFile::setIncremental(bool value) { _IsIncremental=value; // if we're flagged as non-incremental then we don't need a version history if (!_IsIncremental && _Versions.size()>1) { _Versions[0]= _Versions.back(); _Versions.resize(1); } } bool CBNPFile::isIncremental() { return _IsIncremental; } //----------------------------------------------------------------------------- // Persistent data for CBNPFile //----------------------------------------------------------------------------- #define PERSISTENT_CLASS CBNPFile #define PERSISTENT_DATA\ PROP(std::string,_FileName)\ STRUCT_VECT(_Versions) //# pragma message( PERSISTENT_GENERATION_MESSAGE ) #include "persistent_data_template.h" #undef PERSISTENT_CLASS #undef PERSISTENT_DATA //----------------------------------------------------------------------------- // class CBNPFileSet //----------------------------------------------------------------------------- void CBNPFileSet::removeFile(const std::string &filename) { for( uint k = 0; k < _Files.size(); ++k) { if (_Files[k].getFileName() == filename) { _Files.erase(_Files.begin() + k); } } } // add a version to the file // returns highest version number in files after operation uint32 CBNPFileSet::addVersion(const std::string& bnpDirectory, const std::string& refDirectory, IVersionNumberGenerator& version) { nlinfo("Updating package index..."); uint32 result=0; // add versions to different files for (uint32 i=(uint32)_Files.size();i--;) if (_Files[i].addVersion(bnpDirectory,refDirectory,version)!=false) result= std::max(result,_Files[i].getLatestVersionNumber()); return result; } // look through the referenced files for the highest version number uint32 CBNPFileSet::getVersionNumber() const { uint32 result=0; for (uint32 i=(uint32)_Files.size();i--;) result= std::max(result,_Files[i].getLatestVersionNumber()); return result; } void CBNPFileSet::clear() { _Files.clear(); } uint32 CBNPFileSet::fileCount() const { return (uint32)_Files.size(); } const CBNPFile& CBNPFileSet::getFile(uint32 idx) const { return const_cast<CBNPFileSet*>(this)->getFile(idx); } const CBNPFile* CBNPFileSet::getFileByName(const std::string& fileName) const { return const_cast<CBNPFileSet*>(this)->getFileByName(fileName); } CBNPFile& CBNPFileSet::getFile(uint32 idx) { nlassert(idx<fileCount()); return _Files[idx]; } CBNPFile* CBNPFileSet::getFileByName(const std::string& fileName) { // look for the file by name for (uint32 i=0;i<fileCount();++i) if (getFile(i).getFileName()==fileName) return &getFile(i); // file not found so return NULL return NULL; } void CBNPFileSet::addFile(const std::string& fileName,bool isIncremental) { // see if the file already exists in the files container if (getFileByName(fileName)!=NULL) { if (!isIncremental) getFileByName(fileName)->setIncremental(false); return; } // file is new so need to add it std::string s= fileName; normaliseBnpFileName(s); nlinfo("- adding file: %s",s.c_str()); _Files.resize(_Files.size()+1); _Files.back().setFileName(s); _Files.back().setIncremental(isIncremental); } //----------------------------------------------------------------------------- // Persistent data for CBNPFileSet //----------------------------------------------------------------------------- #define PERSISTENT_CLASS CBNPFileSet #define PERSISTENT_DATA\ STRUCT_VECT(_Files) //# pragma message( PERSISTENT_GENERATION_MESSAGE ) #include "persistent_data_template.h" #undef PERSISTENT_CLASS #undef PERSISTENT_DATA //----------------------------------------------------------------------------- // class CBNPCategory //----------------------------------------------------------------------------- CBNPCategory::CBNPCategory() { _IsOptional=true; _IsIncremental=true; _Hidden=false; } bool CBNPCategory::hasFile(const std::string &fileName) const { return std::find(_Files.begin(), _Files.end(), fileName) != _Files.end(); } const std::string& CBNPCategory::getName() const { return _Name; } void CBNPCategory::setName(const std::string& name) { _Name=name; } void CBNPCategory::setOptional(bool value) { _IsOptional= value; } bool CBNPCategory::isOptional() const { return _IsOptional; } void CBNPCategory::setUnpackTo(const std::string &n) { _UnpackTo = n; } const std::string &CBNPCategory::getUnpackTo() const { return _UnpackTo; } void CBNPCategory::setIncremental(bool value) { _IsIncremental= value; } bool CBNPCategory::isIncremental() const { return _IsIncremental; } void CBNPCategory::setCatRequired(const std::string &cat) { _CatRequired = cat; } const std::string &CBNPCategory::getCatRequired() const { return _CatRequired; } void CBNPCategory::setHidden(bool value) { _Hidden = value; } bool CBNPCategory::isHidden() const { return _Hidden; } uint32 CBNPCategory::fileCount() const { return (uint32)_Files.size(); } const std::string& CBNPCategory::getFile(uint32 idx) const { nlassert(idx<fileCount()); return _Files[idx]; } void CBNPCategory::addFile(const std::string& fileName) { // make sure file doesn't already exist for (uint32 i=0;i<_Files.size();++i) if (_Files[i]==fileName) return; // add the new file _Files.push_back(fileName); } //----------------------------------------------------------------------------- // Persistent data for CBNPCategory //----------------------------------------------------------------------------- #define PERSISTENT_CLASS CBNPCategory #define PERSISTENT_DATA\ PROP(std::string, _Name)\ LPROP(bool, _IsOptional, if(!_IsOptional))\ LPROP(std::string, _UnpackTo, if(!_UnpackTo.empty()))\ LPROP(bool, _IsIncremental, if(!_IsIncremental))\ LPROP(std::string, _CatRequired, if(!_CatRequired.empty()))\ LPROP(bool, _Hidden, if(_Hidden))\ PROP_VECT(std::string, _Files)\ //# pragma message( PERSISTENT_GENERATION_MESSAGE ) #include "persistent_data_template.h" #undef PERSISTENT_CLASS #undef PERSISTENT_DATA //----------------------------------------------------------------------------- // class CBNPCategorySet //----------------------------------------------------------------------------- void CBNPCategorySet::clear() { _Category.clear(); } const CBNPCategory* CBNPCategorySet::getCategoryFromFile(const std::string &fileName) const { for(std::vector<CBNPCategory>::const_iterator it = _Category.begin(); it != _Category.end(); ++it) { if (it->hasFile(fileName)) { return &(*it); } } return NULL; } void CBNPCategorySet::deleteCategory(uint32 index) { nlassert(index < _Category.size()); _Category.erase(_Category.begin() + index); } uint32 CBNPCategorySet::fileCount() const { uint32 result=0; for (uint32 i=0;i<_Category.size();++i) result+=_Category[i].fileCount(); return result; } const std::string& CBNPCategorySet::getFile(uint32 idx) const { uint32 i=0; for (;;++i) { nlassert(i<_Category.size()); if (_Category[i].fileCount()>idx) break; idx-=_Category[i].fileCount(); } return _Category[i].getFile(idx); } uint32 CBNPCategorySet::categoryCount() const { return (uint32)_Category.size(); } CBNPCategory& CBNPCategorySet::getCategory(uint32 idx) { nlassert(idx<categoryCount()); return _Category[idx]; } const CBNPCategory& CBNPCategorySet::getCategory(uint32 idx) const { return const_cast<CBNPCategorySet*>(this)->getCategory(idx); } const CBNPCategory* CBNPCategorySet::getCategory(const std::string& categoryName) const { // look for a category with matching name for (uint32 i=0;i<categoryCount();++i) if (getCategory(i).getName()==categoryName) return &(getCategory(i)); return NULL; } // check whether a named category exists and add a new one if need be CBNPCategory* CBNPCategorySet::getCategory(const std::string& categoryName, bool addIfNotExist) { // look for a category with matching name for (uint32 i=0;i<categoryCount();++i) if (getCategory(i).getName()==categoryName) return &(getCategory(i)); // the category wasn't found so return NULL if need be if (!addIfNotExist) return NULL; // create a new category if need be _Category.resize(_Category.size()+1); _Category.back().setName(categoryName); nlinfo("- New category created: %s",categoryName.c_str()); return &_Category.back(); } void CBNPCategorySet::addFile(const std::string& categoryName,const std::string& fileName) { // make sure the category exists CBNPCategory* theCategory= getCategory(categoryName,true); // look to see if the file already exists in the category for (uint32 i=0;i<theCategory->fileCount();++i) if (theCategory->getFile(i)==fileName) return; // the file doesn't already exist so add it theCategory->addFile(fileName); nlinfo("- File added to category %s::%s",categoryName.c_str(),fileName.c_str()); } bool CBNPCategorySet::isFileIncremental(const std::string& fileName) const { // for each category for (uint32 i=0;i<categoryCount();++i) { const CBNPCategory& theCategory= getCategory(i); // if the category is incremental then skip it if (theCategory.isIncremental()) continue; // if the file exists in this category then return 'false' meaning non-incremental for (uint32 i=0;i<theCategory.fileCount();++i) if (theCategory.getFile(i)==fileName) return false; } // the file wasn't found in a non-incremental category so it must be incremental return true; } //----------------------------------------------------------------------------- // Persistent data for CBNPCategorySet //----------------------------------------------------------------------------- #define PERSISTENT_CLASS CBNPCategorySet #define PERSISTENT_DATA\ STRUCT_VECT(_Category) //# pragma message( PERSISTENT_GENERATION_MESSAGE ) #include "persistent_data_template.h" #undef PERSISTENT_CLASS #undef PERSISTENT_DATA //----------------------------------------------------------------------------- // class CProductDescriptionForClient //----------------------------------------------------------------------------- void CProductDescriptionForClient::clear() { _Categories.clear(); _Files.clear(); } void CProductDescriptionForClient::setCategories(CPersistentDataRecord &pdr) { _Categories.clear(); _Categories.apply(pdr); } void CProductDescriptionForClient::setFiles(CPersistentDataRecord &pdr) { _Files.clear(); _Files.apply(pdr); } void CProductDescriptionForClient::getCategories(CPersistentDataRecord &pdr) { pdr.clear(); _Categories.store(pdr); } void CProductDescriptionForClient::getFiles(CPersistentDataRecord &pdr) { pdr.clear(); _Files.store(pdr); } bool CProductDescriptionForClient::load(const std::string& filePath) { // read new contents from input file if (!NLMISC::CFile::fileExists(filePath)) return false; clear(); static CPersistentDataRecord pdr; pdr.clear(); pdr.readFromBinFile(filePath.c_str()); apply(pdr); return true; } void CProductDescriptionForClient::serial(NLMISC::IStream &f) { static CPersistentDataRecord pdr("RyzomTokenFamily"); pdr.clear(); if (f.isReading()) { bool ok = pdr.fromBuffer(f); if (ok) { apply(pdr); } else { throw NLMISC::Exception("Can't retrieve file desc"); } } else { store(pdr); pdr.toStream(f); } } //----------------------------------------------------------------------------- // Persistent data for CProductDescriptionForClient //----------------------------------------------------------------------------- #define PERSISTENT_CLASS CProductDescriptionForClient #define PERSISTENT_DATA\ STRUCT(_Files)\ STRUCT(_Categories) //# pragma message( PERSISTENT_GENERATION_MESSAGE ) #include "persistent_data_template.h" #undef PERSISTENT_CLASS #undef PERSISTENT_DATA //================================================================================================ //================================================================================================ //================================================================================================ //================================================================================================ //#if 0 // ////----------------------------------------------------------------------------- //// class CBNPPatchDescription ////----------------------------------------------------------------------------- //// a little object used to describe patches in CBNPUnpatcher class // //std::string CBNPPatchDescription::getPatchFileName() const //{ // return NLMISC::CFile::getFilenameWithoutExtension(getTargetFileName())+NLMISC::toString("_%05d.patch",getVersion()); //} // // ////----------------------------------------------------------------------------- //// class CBNPUnpatcher ////----------------------------------------------------------------------------- // ////----------------------------------------------------------------------------- //// initialisation // //CBNPUnpatcher::CBNPUnpatcher(const std::string& productName,uint32 version,const std::string& appRootDirectory,const std::string& patchDirectory) //{ // _AppRootDirectory= NLMISC::CPath::standardizePath(appRootDirectory,true); // _PatchDirectory= NLMISC::CPath::standardizePath(patchDirectory,true); // _ProductName= productName; // _Version= version; //} // //bool CBNPUnpatcher::isIndexUpToDate() //{ // return (_Files.getVersionNumber()==_Version); //} // //CBNPPatchDescription CBNPUnpatcher::getIndexFileDownloadDescription() //{ // return CBNPPatchDescription(productName+"_patch_index",_Version,0,!isIndexUpToDate()) //} // // ////----------------------------------------------------------------------------- //// accessors for directories // //std::string getRootDirectory() const //{ // return _AppRootDirectory; //} // //std::string getDataDirectory() const //{ // return _AppRootDirectory+"data/"; //} // //std::string getPatchDirectory() const //{ // return _PatchDirectory; //} // // ////----------------------------------------------------------------------------- //// accessors for retrieving info on required patches // //bool CBNPUnpatcher::isUpToDate() //{ // return (isIndexUpToDate() && !isPatchMandatory() && !isPatchOptional()) //} // //bool CBNPUnpatcher::_isPatch(bool isBySelectionFlag,bool isOptionalFlag=false) //{ // nlassert(isIndexUpToDate()==true); // // // scan all categories for a mandatoy category with non-up-to-date files // for (uint32 i=0;i<_Categories.categoryCount();++i) // { // CBNPCategory* theCategory= _Categories.getCategory(i); // // // decide whether or not to skip this category // if (isBySelectionFlag==true) // { // if (theCategory->isOptional() && // _SelectedCategories.find(theCategory->getName())==_SelectedCategories.end())) // continue; // } // else // { // if (theCategory->isOptional()!=isOptionalFlag) // continue; // } // // // if one of the files is not up to date then we return 'true' as we need to patch // for (uint32 j=0;j<theCategory->fileCount();++j) // if (!isFileUpToDate(theCategory->getFile(j))) // return true; // } // // return false; //} // //bool CBNPUnpatcher::isPatchMandatory() //{ // return _isPatch(false,false); //} // //bool CBNPUnpatcher::isPatchOptional() //{ // return _isPatch(false,true); //} // //bool CBNPUnpatcher::isPatchRequired() //{ // return _isPatch(true); //} // //// return true if it's necessary to download patches for the selected options //bool CBNPUnpatcher::isDownloadRequired() //{ // if (!isPatchRequired()) // return false; // // std::vector<CBNPPatchDescription> hold; // getDownloadPatches(hold); // return !hold.empty(); //} // //// return true if it's necessary to download the next patch that needs to be applied (in order) //bool CBNPUnpatcher::isNextPatchDownloadRequired() //{ // if (!isPatchRequired()) // return false; // // return getNextPatch().getRequiresDownload(); //} // // ////----------------------------------------------------------------------------- //// crunching routines // //// scan the directories for files - identifies the set of required patches //// and also the set of these patches that is missing from the patch directory //void CBNPUnpatcher::scanForFiles() //{ // std::vector<std::string> patchFiles; // std::vector<std::string> patchFiles; // std::vector<std::string> dataFiles; // // // get the list of files in the patch directory // NLMISC::CPath::getPathContent(getPatchDirectory(),false,false,true,patchFiles); // // // get the list of files in the data directory // NLMISC::CPath::getPathContent(getDataDirectory(),false,false,true,dataFiles); // // for (uint32 i=0;i<_Categories.fileCount();++i) // { // _Categories.getFile() // result.push_back(_Categories.getCategory(i).getName()); // } // xxx //} // //// apply the mandatory and selected optional patches //// nlerror if isDownloadRequired() is not false //void CBNPUnpatcher::applyPatches() //{ // nlassert(isIndexUpToDate()==true); // nlassert(!isDownloadRequired()); // xxx //} // //// apply the next patch (in order) //// nlerror if isNextPatchDownloadRequired() is not false //void CBNPUnpatcher::applyNextPatch() //{ // // note that if the index isn't up to date then it is classed as the next patch // nlassert(!isNextPatchDownloadRequired()); // xxx //} // // ////----------------------------------------------------------------------------- //// managing the set of selected optional patch categories // //// get the names of all optional categories //void CBNPUnpatcher::getAllOptionalCategories(std::vector<std::string>& result) //{ // nlassert(isIndexUpToDate()==true); // // result.clear(); // for (uint32 i=0;i<_Categories.categoryCount();++i) // { // result.push_back(_Categories.getCategory(i).getName()); // } //} // //// get the names of the optional categories that require patching //void CBNPUnpatcher::getPatchableOptionalCategories(std::vector<std::string>& result) //{ // nlassert(isIndexUpToDate()==true); // // result.clear(); // for (uint32 i=0;i<_Categories.categoryCount();++i) // { // CBNPCategory* theCategory= _Categories.getCategory(i); // uint32 j; // // // if one of the files is not up to date then we return 'true' as we need to patch // for (j=0;j<theCategory->fileCount();++j) // if (!isFileUpToDate(theCategory->getFile(j))) // break; // // // if we broke out before the end of the for loop then we need to add this category // if (j<theCategory->fileCount()) // result.push_back(_Categories.getCategory(i).getName()); // } //} // //// select or unselect an optional package //void CBNPUnpatcher::setOptionalCategorySelectFlag(const std::string& categoryName, bool value) //{ // nlassert(isIndexUpToDate()==true); // _SelectedCategories.insert(categoryName); //} // //// select or unselect all optional packages //void CBNPUnpatcher::setAllOptionalCategorySelectFlags(bool value) //{ // nlassert(isIndexUpToDate()==true); // // _SelectedCategories.clear(); // for (uint32 i=0;i<_Categories.categoryCount();++i) // { // _SelectedCategories.insert(_Categories.getCategory(i).getName()); // } //} // // ////----------------------------------------------------------------------------- //// getting lists of applicable patches // //// get the ordered list of mandatory + optional patches that need to be applied to update selected packages //void CBNPUnpatcher::getSelectedPatches(std::vector<CBNPPatchDescription>& result) //{ // nlassert(isIndexUpToDate()==true); // // std::vector<CBNPPatchDescription> mandatoryPatches; // getMandatoryPatches(mandatoryPatches); // // std::vector<CBNPPatchDescription> optionalPatches; // getSelectedOptionalPatches(optionalPatches); // // result= mandatoryPatches+ optionalPatches; //} // //// get the ordered list of optional patches that need to be applied to update selected packages //void CBNPUnpatcher::getSelectedOptionalPatches(std::vector<CBNPPatchDescription>& result) //{ // nlassert(isIndexUpToDate()==true); // xxx //} // //// get the ordered list of patches that need to be applied for a minimum update //void CBNPUnpatcher::getMandatoryPatches(std::vector<CBNPPatchDescription>& result) //{ // nlassert(isIndexUpToDate()==true); // xxx //} // //// get an ordered list of the patches that need to be applied for a full update //void CBNPUnpatcher::getAllPatches(std::vector<CBNPPatchDescription>& result) //{ // // store the selected category set in temporary variable // std::set<std::string> selectedCategories= _SelectedCategories; // // // select all of the categories and delegate to getSelectedPatches() // setAllOptionalCategorySelectFlags(); // getSelectedPatches(result); // // // restore the _SelectedCategories set from temp variable // _SelectedCategories= selectedCategories; //} // //// get the name of the next patch that needs to be applied (for progress display) //const std::string& CBNPUnpatcher::getNextPatchName() //{ // CBNPPatchDescription patch= getNextPatch(); // return patch.getTargetFileName()+NLMISC::toString(":%d",patch.getVersion()); //} // //// get the patch description for the next patch to apply //CBNPPatchDescription CBNPUnpatcher::getNextPatch() //{ // // make sure that index is up to date and patching is required // nlassert(isIndexUpToDate()); // nlassert(isPatchRequired()); // // // treat the case of !uptodate() here and get the index file as the next patch // if (!isIndexUpToDate()) // { // return getIndexFileDownloadDescription(); // } // // for (uint32 i=0;i<_Categories.categoryCount();++i) // { // CBNPCategory* theCategory= _Categories.getCategory(i); // uint32 j; // // // if one of the files is not up to date then we return 'true' as we need to patch // for (j=0;j<theCategory->fileCount();++j) // if (!isFileUpToDate(theCategory->getFile(j))) // break; // // // if we broke out before the end of the for loop then we need to add this category // if (j<theCategory->fileCount()) // result.push_back(_Categories.getCategory(i).getName()); // } // // xxx //} // //// get the list of patches that need to be downloaded //void CBNPUnpatcher::getSelectedDownloadPatches(std::vector<CBNPPatchDescription>& result) //{ // nlassert(isIndexUpToDate()==true); // xxx //} // //// get the list of patches that need to be downloaded //void CBNPUnpatcher::getAllDownloadPatches(std::vector<CBNPPatchDescription>& result) //{ // // store the selected category set in temporary variable // std::set<std::string> selectedCategories= _SelectedCategories; // // // select all of the categories and delegate to getSelectedDownloadPatches() // setAllOptionalCategorySelectFlags(); // getSelectedDownloadPatches(result); // // // restore the _SelectedCategories set from temp variable // _SelectedCategories= selectedCategories; //} // // ////----------------------------------------------------------------------------- // // //#endif