Implement the first step toward Multi-Arch by setting up a Group
authorDavid Kalnischkies <kalnischkies@gmail.com>
Sat, 19 Dec 2009 15:25:56 +0000 (16:25 +0100)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Sat, 19 Dec 2009 15:25:56 +0000 (16:25 +0100)
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!

apt-pkg/cacheiterators.h
apt-pkg/deb/deblistparser.cc
apt-pkg/deb/deblistparser.h
apt-pkg/pkgcache.cc
apt-pkg/pkgcache.h
apt-pkg/pkgcachegen.cc
apt-pkg/pkgcachegen.h

index 1da5c6f..35d3aa2 100644 (file)
 #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;
@@ -75,6 +73,35 @@ template<typename Str, typename Itr> class pkgCache::Iterator {
        // Constructors - look out for the variable assigning
        inline Iterator() : S(0), Owner(0) {};
        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                                                    /*{{{*/
@@ -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
index 25a1df3..fe68aec 100644 (file)
@@ -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
index 1c70922..5f91e07 100644 (file)
@@ -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();
index 2f8bde6..2b5f53f 100644 (file)
@@ -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];
    }
 };
                                                                        /*}}}*/
index 359f8a5..b3d2752 100644 (file)
@@ -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
index 68180c7..c37f6f4 100644 (file)
@@ -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
index 108b342..4a2419b 100644 (file)
@@ -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;