void CServerPatchApplier::patchFromLive(uint32 liveVersion, uint32 installRequestVersion) { // scan the temp directory to build a file list and delete all of the files we find there CFileDescriptionContainer tempFiles; tempFiles.addFileSpec(_Directories.installDirectoryName()+"*",true); for (uint32 i=0;i<tempFiles.size();++i) { NLMISC::CFile::deleteFile(tempFiles[i].FileName); } // make sure the temp directory is now empty tempFiles.clear(); tempFiles.addFileSpec(_Directories.installDirectoryName()+"*",true); DROP_IF(!tempFiles.empty(),"Failed to delete all of the contents of the directory: "+_Directories.installDirectoryName(),return); // choose a patch direction depending on the whether we're patching forwards or backwards if (liveVersion<installRequestVersion) { _patchUpFromLive(liveVersion,installRequestVersion); } else if (liveVersion>installRequestVersion) { _patchDownFromLive(liveVersion,installRequestVersion); } }
bool CCharacterScanJob::deleteFilesInOutputDirectory() const { CFileDescriptionContainer fdc; fdc.addFileSpec(STAT_GLOBALS::getOutputFilePath(getOutputPath()+"*")); for (uint32 i=0;i<fdc.size();++i) { NLMISC::CFile::deleteFile(fdc[i].FileName); } // make sure the directory is now empty fdc.clear(); fdc.addFileSpec(STAT_GLOBALS::getOutputFilePath(getOutputPath()+"*")); return fdc.empty(); }
static void addToFdc(const NLMISC::CSString& filespec, CFileDescriptionContainer& result) { if (filespec.left(1)=="@") { readFileList(filespec.leftCrop(1),result); } else { result.addFileSpec(filespec); } }
bool CCharScanScriptFile::applyToJob(CCharacterScanJob& job) { bool result=true; // apply the file names CFileDescriptionContainer fdc; for (uint32 i=0;i<_InputFiles.size();++i) { fdc.addFileSpec(_InputFiles[i]); } job.addFiles(fdc); // apply the filters for (uint32 i=0;i<_Filters.size();++i) { ICharFilter* filter= CCharFilterFactory::getInstance()->build(_Filters[i]); if (filter==NULL) { nlwarning("Failed to build filter description from line: %s",_Filters[i].c_str()); result=false; continue; } job.addFilter(filter); } // apply the info extractors for (uint32 i=0;i<_InfoExtractors.size();++i) { ICharInfoExtractor* infoExtractor= CCharInfoExtractorFactory::getInstance()->build(_InfoExtractors[i]); if (infoExtractor==NULL) { nlwarning("Failed to build filter description from line: %s",_InfoExtractors[i].c_str()); result=false; continue; } job.addInfoExtractor(infoExtractor); } // apply the output path job.setOutputPath(_OutputPath); return result; }
void CServerPatchApplier::_patchUpFromLive(uint32 liveVersion, uint32 installRequestVersion) { nlinfo("SPA %s: Patching up from version %d to %d",_Directories.getDomainName().c_str(),liveVersion,installRequestVersion); // scan the patch directory to build a file list CFileDescriptionContainer patchFiles; patchFiles.addFileSpec(_Directories.patchDirectoryName()+"*",true); // build map of dest file name to patch vector, filtering out patches later than 'version' typedef std::map<NLMISC::CSString,std::vector<uint32> > TFilePatches; typedef std::set<NLMISC::CSString> TRequiredPaths; TFilePatches filePatches; TRequiredPaths requiredPaths; for (uint32 i=0;i<patchFiles.size();++i) { CSString name= patchFiles[i].FileName.leftCrop(_Directories.patchDirectoryName().size()).splitTo(".patch_"); uint32 patchNum= patchFiles[i].FileName.splitFrom(".patch_").atoi(); DROP_IF(patchNum==0,"Failed to identify patch number in file name: "+patchFiles[i].FileName,continue); if (patchNum<=installRequestVersion) { filePatches[name].push_back(patchNum); } requiredPaths.insert(NLMISC::CFile::getPath(name)); } // create any paths that we're going to need for (TRequiredPaths::iterator it= requiredPaths.begin(); it!=requiredPaths.end(); ++it) { NLMISC::CFile::createDirectoryTree(_Directories.installDirectoryName()+*it); } // run through the file list copying or patching as required TFilePatches::iterator it= filePatches.begin(); TFilePatches::iterator itEnd= filePatches.end(); for (;it!=itEnd;++it) { // skip files that don't exist in the requested patch version if (it->second.empty()) { continue; } // sort the patch vector std::sort(it->second.begin(),it->second.end()); // identify the first patch beyond the patch in this file beyond 'liveVersion' uint32 patchIdx=0; while (patchIdx< it->second.size() && it->second[patchIdx]<=liveVersion) { ++patchIdx; } // if there is no change between the live file and install file then copy the live file if (patchIdx==it->second.size()) { nlinfo("COPY: %s from %s",(_Directories.installDirectoryName()+it->first).c_str(),(_Directories.liveDirectoryName()+it->first).c_str()); NLMISC::CFile::copyFile((_Directories.installDirectoryName()+it->first).c_str(),(_Directories.liveDirectoryName()+it->first).c_str()); untarIfNeeded(_Directories.installDirectoryName()+it->first); continue; } // setup a little boolean to flag errors bool ok= true; // try to apply the first patch in the patch vector by using the file in the current version directory if (patchIdx!=0) { ok= applyPatch( NLMISC::toString("%s%s.patch_%d",_Directories.patchDirectoryName().c_str(),it->first.c_str(),it->second[patchIdx]), _Directories.liveDirectoryName()+it->first, _Directories.installDirectoryName()+it->first+((patchIdx&1)==0?".tmp0":".tmp1")); DROP_IF(!ok,"Failed to apply patch ... rewinding and trying to buid file from 0 for file: "+it->first,patchIdx=0); } // if the patch index is 0 then start by applying the first patch... if (patchIdx ==0) { ok= applyFirstPatch(NLMISC::toString("%s%s.patch_%d",_Directories.patchDirectoryName().c_str(),it->first.c_str(),it->second[0]), _Directories.installDirectoryName()+it->first+".tmp0"); DROP_IF(!ok,"Error: skipping file because failed to apply fist patch: "+it->first,continue); } // run through the remaining patches aplying them iteratively... while(++patchIdx < it->second.size()) { ok= applyPatch( NLMISC::toString("%s%s.patch_%d",_Directories.patchDirectoryName().c_str(),it->first.c_str(),it->second[patchIdx]), _Directories.installDirectoryName()+it->first+((patchIdx&1)==0?".tmp1":".tmp0"), _Directories.installDirectoryName()+it->first+((patchIdx&1)==0?".tmp0":".tmp1")); DROP_IF(!ok,NLMISC::toString("Failed to apply patch %d ... for file: ",it->second[patchIdx])+it->first,break); } // if we bombed out during patch apply then skip this file and continue if (!ok) continue; // we're done so rename the last file generated and delete it's twin finalisePatch(_Directories.installDirectoryName(), it->first, it->second.size()); }