1162 lines
32 KiB
C++
1162 lines
32 KiB
C++
// 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
|