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();
}
Beispiel #3
0
static void addToFdc(const NLMISC::CSString& filespec, CFileDescriptionContainer& result)
{
	if (filespec.left(1)=="@")
	{
		readFileList(filespec.leftCrop(1),result);
	}
	else
	{
		result.addFileSpec(filespec);
	}
}
Beispiel #4
0
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());
	}