#include <apt-pkg/strutl.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/macros.h>
#include <apt-pkg/tagfile.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
-#include <system.h>
/*}}}*/
typedef vector<pkgIndexFile *>::iterator FileIterator;
/* As we handle Arch all packages as architecture bounded
we add all information to every (simulated) arch package */
std::vector<string> genArch;
- if (List.ArchitectureAll() == true)
+ if (List.ArchitectureAll() == true) {
genArch = APT::Configuration::getArchitectures();
- else
+ if (genArch.size() != 1)
+ genArch.push_back("all");
+ } else
genArch.push_back(List.Architecture());
for (std::vector<string>::const_iterator arch = genArch.begin();
for (pkgCache::GrpIterator G = GetCache().GrpBegin(); G.end() != true; G++) {
string const PkgName = G.Name();
for (pkgCache::PkgIterator P = G.PackageList(); P.end() != true; P = G.NextPkg(P)) {
+ if (strcmp(P.Arch(),"all") == 0)
+ continue;
+ pkgCache::PkgIterator allPkg;
for (pkgCache::VerIterator V = P.VersionList(); V.end() != true; V++) {
- string const Arch = V.Arch();
+ string const Arch = V.Arch(true);
map_ptrloc *OldDepLast = NULL;
/* MultiArch handling introduces a lot of implicit Dependencies:
- MultiArch: same → Co-Installable if they have the same version
- All others conflict with all other group members */
bool const coInstall = (V->MultiArch == pkgCache::Version::All ||
V->MultiArch == pkgCache::Version::Same);
+ if (V->MultiArch == pkgCache::Version::All && allPkg.end() == true)
+ allPkg = G.FindPkg("all");
for (vector<string>::const_iterator A = archs.begin(); A != archs.end(); ++A) {
if (*A == Arch)
continue;
NewDepends(D, V, V.VerStr(),
pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks,
OldDepLast);
+ if (V->MultiArch == pkgCache::Version::All) {
+ // Depend on ${self}:all which does depend on nothing
+ NewDepends(allPkg, V, V.VerStr(),
+ pkgCache::Dep::Equals, pkgCache::Dep::Depends,
+ OldDepLast);
+ }
} else {
// Conflicts: ${self}:other
NewDepends(D, V, "",
// ---------------------------------------------------------------------
/* */
bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
- const string &PackageName,
+ const string &PkgName,
+ const string &PkgArch,
const string &Version)
{
pkgCache &Cache = Owner->Cache;
// We do not add self referencing provides
- if (unlikely(Ver.ParentPkg().Name() == PackageName))
+ if (Ver.ParentPkg().Name() == PkgName && PkgArch == Ver.Arch(true))
return true;
// Get a structure
// Locate the target package
pkgCache::PkgIterator Pkg;
- if (unlikely(Owner->NewPackage(Pkg,PackageName,string(Ver.Arch())) == false))
+ if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false))
return false;
// Link it to the package
static bool CheckValidity(const string &CacheFile, FileIterator Start,
FileIterator End,MMap **OutMap = 0)
{
+ bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
// No file, certainly invalid
if (CacheFile.empty() == true || FileExists(CacheFile) == false)
+ {
+ if (Debug == true)
+ std::clog << "CacheFile doesn't exist" << std::endl;
return false;
-
+ }
+
// Map it
FileFd CacheF(CacheFile,FileFd::ReadOnly);
SPtr<MMap> Map = new MMap(CacheF,0);
pkgCache Cache(Map);
if (_error->PendingError() == true || Map->Size() == 0)
{
+ if (Debug == true)
+ std::clog << "Errors are pending or Map is empty()" << std::endl;
_error->Discard();
return false;
}
SPtrArray<bool> Visited = new bool[Cache.HeaderP->PackageFileCount];
memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount);
for (; Start != End; Start++)
- {
+ {
+ if (Debug == true)
+ std::clog << "Checking PkgFile " << (*Start)->Describe() << ": ";
if ((*Start)->HasPackages() == false)
+ {
+ if (Debug == true)
+ std::clog << "Has NO packages" << std::endl;
continue;
+ }
if ((*Start)->Exists() == false)
{
_error->WarningE("stat",_("Couldn't stat source package list %s"),
(*Start)->Describe().c_str());
#endif
+ if (Debug == true)
+ std::clog << "file doesn't exist" << std::endl;
continue;
}
// FindInCache is also expected to do an IMS check.
pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
if (File.end() == true)
+ {
+ if (Debug == true)
+ std::clog << "FindInCache returned end-Pointer" << std::endl;
return false;
+ }
Visited[File->ID] = true;
+ if (Debug == true)
+ std::clog << "with ID " << File->ID << " is valid" << std::endl;
}
for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
if (Visited[I] == false)
+ {
+ if (Debug == true)
+ std::clog << "File with ID" << I << " wasn't visited" << std::endl;
return false;
+ }
if (_error->PendingError() == true)
{
+ if (Debug == true)
+ {
+ std::clog << "Validity failed because of pending errors:" << std::endl;
+ _error->DumpErrors();
+ }
_error->Discard();
return false;
}
bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
MMap **OutMap,bool AllowMem)
{
- unsigned long MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024);
+ bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
+ unsigned long const MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024);
vector<pkgIndexFile *> Files;
for (vector<metaIndex *>::const_iterator i = List.begin();
Files.push_back (*j);
}
- unsigned long EndOfSource = Files.size();
+ unsigned long const EndOfSource = Files.size();
if (_system->AddStatusFiles(Files) == false)
return false;
// Decide if we can write to the files..
- string CacheFile = _config->FindFile("Dir::Cache::pkgcache");
- string SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache");
+ string const CacheFile = _config->FindFile("Dir::Cache::pkgcache");
+ string const SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache");
// Decide if we can write to the cache
bool Writeable = false;
else
if (SrcCacheFile.empty() == false)
Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0;
-
+ if (Debug == true)
+ std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl;
+
if (Writeable == false && AllowMem == false && CacheFile.empty() == false)
return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str());
if (CheckValidity(CacheFile,Files.begin(),Files.end(),OutMap) == true)
{
Progress.OverallProgress(1,1,1,_("Reading package lists"));
+ if (Debug == true)
+ std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
return true;
}
+ else if (Debug == true)
+ std::clog << "pkgcache.bin is NOT valid" << std::endl;
/* At this point we know we need to reconstruct the package cache,
begin. */
Map = new DynamicMMap(*CacheF,MMap::Public,MapSize);
if (_error->PendingError() == true)
return false;
+ if (Debug == true)
+ std::clog << "Open filebased MMap" << std::endl;
}
else
{
// Just build it in memory..
Map = new DynamicMMap(0,MapSize);
+ if (Debug == true)
+ std::clog << "Open memory Map (not filebased)" << std::endl;
}
// Lets try the source cache.
if (CheckValidity(SrcCacheFile,Files.begin(),
Files.begin()+EndOfSource) == true)
{
+ if (Debug == true)
+ std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
// Preload the map with the source cache
FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly);
- unsigned long alloc = Map->RawAllocate(SCacheF.Size());
+ unsigned long const alloc = Map->RawAllocate(SCacheF.Size());
if ((alloc == 0 && _error->PendingError())
|| SCacheF.Read((unsigned char *)Map->Data() + alloc,
SCacheF.Size()) == false)
return false;
TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
-
+
// Build the status cache
pkgCacheGenerator Gen(Map.Get(),&Progress);
if (_error->PendingError() == true)
}
else
{
+ if (Debug == true)
+ std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl;
TotalSize = ComputeSize(Files.begin(),Files.end());
// Build the source cache
// FIXME: move me to a better place
Gen.FinishCache(Progress);
}
+ if (Debug == true)
+ std::clog << "Caches are ready for shipping" << std::endl;
if (_error->PendingError() == true)
return false;