summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2009-12-19 16:25:56 +0100
committerDavid Kalnischkies <kalnischkies@gmail.com>2009-12-19 16:25:56 +0100
commit5bf15716398fdb767ca6249a0155219b88d7ae60 (patch)
tree35a5f1db804539d0fb2d3260d5557a4edde73838 /apt-pkg
parent201d1fa0d25deeda77c2570ee5342eaf18499699 (diff)
Implement the first step toward Multi-Arch by setting up a Group
infrastructor for packages. APT is now aware of the fact that a package A in architecture X can't satisfy a dependency on package A in architecture Y - to handle these packages are now identified by name and architecture, so different architectures of the same package are handled internally as completly different packages. This is great for pinning, dependency checking and in many other situations, but sometimes we need to know which archs are available for a given package: Here Groups come to our rescue!
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/cacheiterators.h37
-rw-r--r--apt-pkg/deb/deblistparser.cc40
-rw-r--r--apt-pkg/deb/deblistparser.h1
-rw-r--r--apt-pkg/pkgcache.cc112
-rw-r--r--apt-pkg/pkgcache.h30
-rw-r--r--apt-pkg/pkgcachegen.cc111
-rw-r--r--apt-pkg/pkgcachegen.h6
7 files changed, 267 insertions, 70 deletions
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h
index 1da5c6f02..35d3aa228 100644
--- a/apt-pkg/cacheiterators.h
+++ b/apt-pkg/cacheiterators.h
@@ -31,10 +31,8 @@
#define PKGLIB_CACHEITERATORS_H
// abstract Iterator template /*{{{*/
/* This template provides the very basic iterator methods we
- need to have for doing some walk-over-the-cache magic, */
+ need to have for doing some walk-over-the-cache magic */
template<typename Str, typename Itr> class pkgCache::Iterator {
- __attribute__ ((deprecated)) void _dummy(); // FIXME: Who on earth uses this method ???
-
protected:
Str *S;
pkgCache *Owner;
@@ -77,6 +75,35 @@ template<typename Str, typename Itr> class pkgCache::Iterator {
inline Iterator(pkgCache &Owner,Str *T = 0) : S(T), Owner(&Owner) {};
};
/*}}}*/
+// Group Iterator /*{{{*/
+/* Packages with the same name are collected in a Group so someone only
+ interest in package names can iterate easily over the names, so the
+ different architectures can be treated as of the "same" package
+ (apt internally treat them as totally different packages) */
+class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
+ protected:
+ inline Group* OwnerPointer() const {
+ return Owner->GrpP;
+ };
+
+ public:
+ void operator ++(int) {if (S != Owner->GrpP) S = Owner->GrpP + S->Next;};
+ virtual void operator ++() {operator ++(0);};
+
+ inline const char *Name() const {return S->Name == 0?0:Owner->StrP + S->Name;};
+ inline PkgIterator PackageList() const;
+ PkgIterator FindPkg(string Arch = "any");
+ PkgIterator NextPkg(PkgIterator const &Pkg);
+
+ // Constructors
+ inline GrpIterator(pkgCache &Owner, Group *Trg) : Iterator<Group, GrpIterator>(Owner, Trg) {
+ if (S == 0)
+ S = OwnerPointer();
+ };
+ inline GrpIterator() : Iterator<Group, GrpIterator>() {};
+
+};
+ /*}}}*/
// Package Iterator /*{{{*/
class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> {
long HashIndex;
@@ -103,6 +130,8 @@ class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> {
inline const char *Section() const {return S->Section == 0?0:Owner->StrP + S->Section;};
inline bool Purge() const {return S->CurrentState == pkgCache::State::Purge ||
(S->CurrentVer == 0 && S->CurrentState == pkgCache::State::NotInstalled);};
+ inline const char *Arch() const {return S->Arch == 0?0:Owner->StrP + S->Arch;};
+ inline GrpIterator Group() const { return GrpIterator(*Owner, Owner->GrpP + S->Group);};
inline VerIterator VersionList() const;
inline VerIterator CurrentVer() const;
@@ -339,6 +368,8 @@ class pkgCache::DescFileIterator : public Iterator<DescFile, DescFileIterator> {
};
/*}}}*/
// Inlined Begin functions cant be in the class because of order problems /*{{{*/
+inline pkgCache::PkgIterator pkgCache::GrpIterator::PackageList() const
+ {return PkgIterator(*Owner,Owner->PkgP + S->FirstPackage);};
inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const
{return VerIterator(*Owner,Owner->VerP + S->VersionList);};
inline pkgCache::VerIterator pkgCache::PkgIterator::CurrentVer() const
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index 25a1df3f9..fe68aec0b 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -53,12 +53,25 @@ unsigned long debListParser::UniqFindTagWrite(const char *Tag)
// ListParser::Package - Return the package name /*{{{*/
// ---------------------------------------------------------------------
/* This is to return the name of the package this section describes */
-string debListParser::Package()
-{
- string Result = Section.FindS("Package");
- if (Result.empty() == true)
- _error->Error("Encountered a section with no Package: header");
- return Result;
+string debListParser::Package() {
+ string const Result = Section.FindS("Package");
+ if(unlikely(Result.empty() == true))
+ _error->Error("Encountered a section with no Package: header");
+ return Result;
+}
+ /*}}}*/
+// ListParser::Architecture - Return the package arch /*{{{*/
+// ---------------------------------------------------------------------
+/* This will return the Architecture of the package this section describes
+ Note that architecture "all" packages will get the architecture of the
+ Packages file parsed here */
+string debListParser::Architecture() {
+ string const Result = Section.FindS("Architecture");
+ if (Result.empty() == true)
+ return Arch;
+ if (Result == "all")
+ return Arch;
+ return Result;
}
/*}}}*/
// ListParser::Version - Return the version string /*{{{*/
@@ -78,8 +91,10 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
{
// Parse the section
Ver->Section = UniqFindTagWrite("Section");
- Ver->Arch = UniqFindTagWrite("Architecture");
-
+
+ // Parse the architecture
+ Ver->Arch = WriteUniqString(Architecture());
+
// Archive Size
Ver->Size = (unsigned)Section.FindI("Size");
@@ -537,6 +552,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
return true;
string Package;
+ string const pkgArch = Ver.Arch();
string Version;
unsigned int Op;
@@ -546,7 +562,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
if (Start == 0)
return _error->Error("Problem parsing dependency %s",Tag);
- if (NewDepends(Ver,Package,Version,Op,Type) == false)
+ if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
return false;
if (Start == Stop)
break;
@@ -619,6 +635,7 @@ bool debListParser::Step()
if (Section.Find("Architecture",Start,Stop) == false)
return true;
+ //FIXME: Accept different Architectures here
if (stringcmp(Arch,Start,Stop) == 0)
return true;
@@ -641,8 +658,9 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
if (Tags.Step(Section) == false)
return false;
- //mvo: I don't think we need to fill that in (it's unused since apt-0.6)
- //FileI->Architecture = WriteUniqString(Arch);
+ // FIXME: Do we need it now for multi-arch?
+ // mvo: I don't think we need to fill that in (it's unused since apt-0.6)
+// FileI->Architecture = WriteUniqString(Arch);
// apt-secure does no longer download individual (per-section) Release
// file. to provide Component pinning we use the section name now
diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h
index 1c709229f..5f91e073e 100644
--- a/apt-pkg/deb/deblistparser.h
+++ b/apt-pkg/deb/deblistparser.h
@@ -46,6 +46,7 @@ class debListParser : public pkgCacheGenerator::ListParser
// These all operate against the current section
virtual string Package();
+ virtual string Architecture();
virtual string Version();
virtual bool NewVersion(pkgCache::VerIterator Ver);
virtual string Description();
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index 2f8bde6f7..2b5f53f6f 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -79,7 +79,8 @@ pkgCache::Header::Header()
StringList = 0;
VerSysName = 0;
Architecture = 0;
- memset(HashTable,0,sizeof(HashTable));
+ memset(PkgHashTable,0,sizeof(PkgHashTable));
+ memset(GrpHashTable,0,sizeof(GrpHashTable));
memset(Pools,0,sizeof(Pools));
}
/*}}}*/
@@ -118,6 +119,7 @@ bool pkgCache::ReMap()
{
// Apply the typecasts.
HeaderP = (Header *)Map.Data();
+ GrpP = (Group *)Map.Data();
PkgP = (Package *)Map.Data();
VerFileP = (VerFile *)Map.Data();
DescFileP = (DescFile *)Map.Data();
@@ -165,7 +167,7 @@ unsigned long pkgCache::sHash(const string &Str) const
unsigned long Hash = 0;
for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
Hash = 5*Hash + tolower_ascii(*I);
- return Hash % _count(HeaderP->HashTable);
+ return Hash % _count(HeaderP->PkgHashTable);
}
unsigned long pkgCache::sHash(const char *Str) const
@@ -173,24 +175,40 @@ unsigned long pkgCache::sHash(const char *Str) const
unsigned long Hash = 0;
for (const char *I = Str; *I != 0; I++)
Hash = 5*Hash + tolower_ascii(*I);
- return Hash % _count(HeaderP->HashTable);
+ return Hash % _count(HeaderP->PkgHashTable);
}
/*}}}*/
// Cache::FindPkg - Locate a package by name /*{{{*/
// ---------------------------------------------------------------------
/* Returns 0 on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::FindPkg(const string &Name)
-{
- // Look at the hash bucket
- Package *Pkg = PkgP + HeaderP->HashTable[Hash(Name)];
- for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
- {
- if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] &&
- stringcasecmp(Name,StrP + Pkg->Name) == 0)
- return PkgIterator(*this,Pkg);
- }
- return PkgIterator(*this,0);
+pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string Arch) {
+ /* We make a detour via the GrpIterator here as
+ on a multi-arch environment a group is easier to
+ find than a package (less entries in the buckets) */
+ pkgCache::GrpIterator Grp = FindGrp(Name);
+ if (Grp.end() == true)
+ return PkgIterator(*this,0);
+
+ return Grp.FindPkg(Arch);
+}
+ /*}}}*/
+// Cache::FindGrp - Locate a group by name /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns End-Pointer on error, pointer to the group otherwise */
+pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
+ if (unlikely(Name.empty() == true))
+ return GrpIterator(*this,0);
+
+ // Look at the hash bucket for the group
+ Group *Grp = GrpP + HeaderP->GrpHashTable[sHash(Name)];
+ for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
+ if (Grp->Name != 0 && StrP[Grp->Name] == Name[0] &&
+ stringcasecmp(Name, StrP + Grp->Name) == 0)
+ return GrpIterator(*this, Grp);
+ }
+
+ return GrpIterator(*this,0);
}
/*}}}*/
// Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
@@ -242,6 +260,68 @@ const char *pkgCache::Priority(unsigned char Prio)
return 0;
}
/*}}}*/
+// GrpIterator::FindPkg - Locate a package by arch /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns an End-Pointer on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) {
+ if (unlikely(IsGood() == false || S->FirstPackage == 0))
+ return PkgIterator(*Owner, 0);
+
+ static string const myArch = _config->Find("APT::Architecture");
+ /* Most of the time the package for our native architecture is
+ the one we add at first to the cache, but this would be the
+ last one we check, so we do it now. */
+ if (Arch == "native" || Arch == myArch) {
+ Arch = myArch;
+ pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
+ if (stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0)
+ return PkgIterator(*Owner, Pkg);
+ }
+
+ /* If we accept any package we simply return the "first"
+ package in this group (the last one added). */
+ if (Arch == "any")
+ return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
+
+ /* Iterate over the list to find the matching arch
+ unfortunately this list includes "package noise"
+ (= different packages with same calculated hash),
+ so we need to check the name also */
+ for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
+ Pkg = Owner->PkgP + Pkg->NextPackage) {
+ if (S->Name == Pkg->Name &&
+ stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0)
+ return PkgIterator(*Owner, Pkg);
+ if ((Owner->PkgP + S->LastPackage) == Pkg)
+ break;
+ }
+
+ return PkgIterator(*Owner, 0);
+}
+ /*}}}*/
+// GrpIterator::NextPkg - Locate the next package in the group /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns an End-Pointer on error, pointer to the package otherwise.
+ We can't simply ++ to the next as the list of packages includes
+ "package noise" (= packages with the same hash value but different name) */
+pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) {
+ if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
+ LastPkg.end() == true))
+ return PkgIterator(*Owner, 0);
+
+ // Iterate over the list to find the next package
+ pkgCache::Package *Pkg = Owner->PkgP + LastPkg.Index();
+ Pkg = Owner->PkgP + Pkg->NextPackage;
+ for (; Pkg != Owner->PkgP; Pkg = Owner->PkgP + Pkg->NextPackage) {
+ if (S->Name == Pkg->Name)
+ return PkgIterator(*Owner, Pkg);
+ if ((Owner->PkgP + S->LastPackage) == Pkg)
+ break;
+ }
+
+ return PkgIterator(*Owner, 0);
+}
+ /*}}}*/
// PkgIterator::operator ++ - Postfix incr /*{{{*/
// ---------------------------------------------------------------------
/* This will advance to the next logical package in the hash table. */
@@ -252,10 +332,10 @@ void pkgCache::PkgIterator::operator ++(int)
S = Owner->PkgP + S->NextPackage;
// Follow the hash table
- while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->HashTable))
+ while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->PkgHashTable))
{
HashIndex++;
- S = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex];
+ S = Owner->PkgP + Owner->HeaderP->PkgHashTable[HashIndex];
}
};
/*}}}*/
diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h
index 359f8a590..b3d2752d2 100644
--- a/apt-pkg/pkgcache.h
+++ b/apt-pkg/pkgcache.h
@@ -32,6 +32,7 @@ class pkgCache /*{{{*/
public:
// Cache element predeclarations
struct Header;
+ struct Group;
struct Package;
struct PackageFile;
struct Version;
@@ -44,6 +45,7 @@ class pkgCache /*{{{*/
// Iterators
template<typename Str, typename Itr> class Iterator;
+ class GrpIterator;
class PkgIterator;
class VerIterator;
class DescIterator;
@@ -97,6 +99,7 @@ class pkgCache /*{{{*/
// Pointers to the arrays of items
Header *HeaderP;
+ Group *GrpP;
Package *PkgP;
VerFile *VerFileP;
DescFile *DescFileP;
@@ -121,7 +124,9 @@ class pkgCache /*{{{*/
const char *Priority(unsigned char Priority);
// Accessors
- PkgIterator FindPkg(const string &Name);
+ GrpIterator FindGrp(const string &Name);
+ PkgIterator FindPkg(const string &Name, string Arch = "native");
+
Header &Head() {return *HeaderP;};
inline PkgIterator PkgBegin();
inline PkgIterator PkgEnd();
@@ -161,6 +166,7 @@ struct pkgCache::Header
unsigned short DescFileSz;
// Structure counts
+ unsigned long GroupCount;
unsigned long PackageCount;
unsigned long VersionCount;
unsigned long DescriptionCount;
@@ -180,22 +186,36 @@ struct pkgCache::Header
/* Allocation pools, there should be one of these for each structure
excluding the header */
- DynamicMMap::Pool Pools[8];
+ DynamicMMap::Pool Pools[9];
- // Rapid package name lookup
- map_ptrloc HashTable[2*1048];
+ // Rapid package and group name lookup
+ // Notice: Increase only both table sizes as the
+ // hashmethod assume the size of the Pkg one
+ map_ptrloc PkgHashTable[2*1048];
+ map_ptrloc GrpHashTable[2*1048];
bool CheckSizes(Header &Against) const;
Header();
};
/*}}}*/
+struct pkgCache::Group { /*{{{*/
+ map_ptrloc Name; // Stringtable
+
+ // Linked List
+ map_ptrloc FirstPackage;// Package
+ map_ptrloc LastPackage; // Package
+ map_ptrloc Next; // Group
+};
+ /*}}}*/
struct pkgCache::Package /*{{{*/
{
// Pointers
map_ptrloc Name; // Stringtable
+ map_ptrloc Arch; // StringTable (StringItem)
map_ptrloc VersionList; // Version
map_ptrloc CurrentVer; // Version
map_ptrloc Section; // StringTable (StringItem)
+ map_ptrloc Group; // Group the Package belongs to
// Linked list
map_ptrloc NextPackage; // Package
@@ -254,7 +274,7 @@ struct pkgCache::Version /*{{{*/
map_ptrloc VerStr; // Stringtable
map_ptrloc Section; // StringTable (StringItem)
map_ptrloc Arch; // StringTable
-
+
// Lists
map_ptrloc FileList; // VerFile
map_ptrloc NextVer; // Version
diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc
index 68180c702..c37f6f48e 100644
--- a/apt-pkg/pkgcachegen.cc
+++ b/apt-pkg/pkgcachegen.cc
@@ -108,12 +108,12 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
while (List.Step() == true)
{
// Get a pointer to the package structure
- string PackageName = List.Package();
+ string const PackageName = List.Package();
if (PackageName.empty() == true)
return false;
-
+
pkgCache::PkgIterator Pkg;
- if (NewPackage(Pkg,PackageName) == false)
+ if (NewPackage(Pkg, PackageName, List.Architecture()) == false)
return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str());
Counter++;
if (Counter % 100 == 0 && Progress != 0)
@@ -323,33 +323,71 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List)
return true;
}
/*}}}*/
+// CacheGenerator::NewGroup - Add a new group /*{{{*/
+// ---------------------------------------------------------------------
+/* This creates a new group structure and adds it to the hash table */
+bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) {
+ Grp = Cache.FindGrp(Name);
+ if (Grp.end() == false)
+ return true;
+
+ // Get a structure
+ unsigned long const Group = Map.Allocate(sizeof(pkgCache::Group));
+ if (unlikely(Group == 0))
+ return false;
+
+ Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
+ Grp->Name = Map.WriteString(Name);
+ if (unlikely(Grp->Name == 0))
+ return false;
+
+ // Insert it into the hash table
+ unsigned long const Hash = Cache.Hash(Name);
+ Grp->Next = Cache.HeaderP->GrpHashTable[Hash];
+ Cache.HeaderP->GrpHashTable[Hash] = Group;
+
+ Cache.HeaderP->GroupCount++;
+
+ return true;
+}
+ /*}}}*/
// CacheGenerator::NewPackage - Add a new package /*{{{*/
// ---------------------------------------------------------------------
/* This creates a new package structure and adds it to the hash table */
-bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name)
-{
- Pkg = Cache.FindPkg(Name);
- if (Pkg.end() == false)
- return true;
+bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name,
+ const string &Arch) {
+ pkgCache::GrpIterator Grp;
+ if (unlikely(NewGroup(Grp, Name) == false))
+ return false;
+
+ Pkg = Grp.FindPkg(Arch);
+ if (Pkg.end() == false)
+ return true;
// Get a structure
- unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
- if (Package == 0)
+ unsigned long const Package = Map.Allocate(sizeof(pkgCache::Package));
+ if (unlikely(Package == 0))
return false;
-
Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
-
+
// Insert it into the hash table
- unsigned long Hash = Cache.Hash(Name);
- Pkg->NextPackage = Cache.HeaderP->HashTable[Hash];
- Cache.HeaderP->HashTable[Hash] = Package;
-
- // Set the name and the ID
- Pkg->Name = Map.WriteString(Name);
- if (Pkg->Name == 0)
+ unsigned long const Hash = Cache.Hash(Name);
+ Pkg->NextPackage = Cache.HeaderP->PkgHashTable[Hash];
+ Cache.HeaderP->PkgHashTable[Hash] = Package;
+
+ // remember the packages in the group
+ Grp->FirstPackage = Package;
+ if (Grp->LastPackage == 0)
+ Grp->LastPackage = Package;
+
+ // Set the name, arch and the ID
+ Pkg->Name = Grp->Name;
+ Pkg->Group = Grp.Index();
+ Pkg->Arch = WriteUniqString(Arch.c_str());
+ if (unlikely(Pkg->Arch == 0))
return false;
Pkg->ID = Cache.HeaderP->PackageCount++;
-
+
return true;
}
/*}}}*/
@@ -474,6 +512,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
version and to the package that it is pointing to. */
bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
const string &PackageName,
+ const string &Arch,
const string &Version,
unsigned int Op,
unsigned int Type)
@@ -481,8 +520,8 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
pkgCache &Cache = Owner->Cache;
// Get a structure
- unsigned long Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency));
- if (Dependency == 0)
+ unsigned long const Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency));
+ if (unlikely(Dependency == 0))
return false;
// Fill it in
@@ -492,11 +531,17 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
Dep->CompareOp = Op;
Dep->ID = Cache.HeaderP->DependsCount++;
- // Locate the target package
- pkgCache::PkgIterator Pkg;
- if (Owner->NewPackage(Pkg,PackageName) == false)
+ pkgCache::GrpIterator Grp;
+ if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
return false;
-
+
+ // Locate the target package
+ pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch);
+ if (Pkg.end() == true) {
+ if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
+ return false;
+ }
+
// Probe the reverse dependency list for a version string that matches
if (Version.empty() == false)
{
@@ -504,7 +549,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
if (I->Version != 0 && I.TargetVer() == Version)
Dep->Version = I->Version;*/
if (Dep->Version == 0)
- if ((Dep->Version = WriteString(Version)) == 0)
+ if (unlikely((Dep->Version = WriteString(Version)) == 0))
return false;
}
@@ -524,7 +569,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
}
// Is it a file dependency?
- if (PackageName[0] == '/')
+ if (unlikely(PackageName[0] == '/'))
FoundFileDeps = true;
Dep->NextDepends = *OldDepLast;
@@ -544,12 +589,12 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
pkgCache &Cache = Owner->Cache;
// We do not add self referencing provides
- if (Ver.ParentPkg().Name() == PackageName)
+ if (unlikely(Ver.ParentPkg().Name() == PackageName))
return true;
// Get a structure
- unsigned long Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
- if (Provides == 0)
+ unsigned long const Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
+ if (unlikely(Provides == 0))
return false;
Cache.HeaderP->ProvidesCount++;
@@ -558,12 +603,12 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
Prv->Version = Ver.Index();
Prv->NextPkgProv = Ver->ProvidesList;
Ver->ProvidesList = Prv.Index();
- if (Version.empty() == false && (Prv->ProvideVersion = WriteString(Version)) == 0)
+ if (Version.empty() == false && unlikely((Prv->ProvideVersion = WriteString(Version)) == 0))
return false;
// Locate the target package
pkgCache::PkgIterator Pkg;
- if (Owner->NewPackage(Pkg,PackageName) == false)
+ if (unlikely(Owner->NewPackage(Pkg,PackageName,string(Ver.Arch())) == false))
return false;
// Link it to the package
diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h
index 108b34207..4a2419b24 100644
--- a/apt-pkg/pkgcachegen.h
+++ b/apt-pkg/pkgcachegen.h
@@ -51,7 +51,8 @@ class pkgCacheGenerator /*{{{*/
// Flag file dependencies
bool FoundFileDeps;
- bool NewPackage(pkgCache::PkgIterator &Pkg,const string &PkgName);
+ bool NewGroup(pkgCache::GrpIterator &Grp,const string &Name);
+ bool NewPackage(pkgCache::PkgIterator &Pkg,const string &Name, const string &Arch);
bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
unsigned long NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next);
@@ -96,7 +97,7 @@ class pkgCacheGenerator::ListParser
inline unsigned long WriteUniqString(const char *S,unsigned int Size) {return Owner->WriteUniqString(S,Size);};
inline unsigned long WriteString(const string &S) {return Owner->Map.WriteString(S);};
inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->Map.WriteString(S,Size);};
- bool NewDepends(pkgCache::VerIterator Ver,const string &Package,
+ bool NewDepends(pkgCache::VerIterator Ver,const string &Package, const string &Arch,
const string &Version,unsigned int Op,
unsigned int Type);
bool NewProvides(pkgCache::VerIterator Ver,const string &Package,
@@ -106,6 +107,7 @@ class pkgCacheGenerator::ListParser
// These all operate against the current section
virtual string Package() = 0;
+ virtual string Architecture() = 0;
virtual string Version() = 0;
virtual bool NewVersion(pkgCache::VerIterator Ver) = 0;
virtual string Description() = 0;