]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/pkgcachegen.cc
fix partial (206 and 416) support in https
[apt.git] / apt-pkg / pkgcachegen.cc
index 2f05310c1750e6e629c64b8075da91ff51565a89..7ce7aba7bc742cd7a56f10d16d6c0b8b82b2e97a 100644 (file)
@@ -296,6 +296,8 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
 
    // Find the right version to write the description
    MD5SumValue CurMd5 = List.Description_md5();
+   if (CurMd5.Value().empty() == true || List.Description().empty() == true)
+      return true;
    std::string CurLang = List.DescriptionLanguage();
 
    for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
@@ -390,7 +392,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
    }
 
    // Add a new version
-   map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer);
+   map_ptrloc const verindex = NewVersion(Ver, Version, Pkg.Index(), Hash, *LastVer);
    if (verindex == 0 && _error->PendingError())
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
                           Pkg.Name(), "NewVersion", 1);
@@ -398,8 +400,6 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
    if (oldMap != Map.Data())
         LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
    *LastVer = verindex;
-   Ver->ParentPkg = Pkg.Index();
-   Ver->Hash = Hash;
 
    if (unlikely(List.NewVersion(Ver) == false))
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
@@ -463,11 +463,8 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
               pkgCache::VerIterator ConVersion = D.ParentVer();
               Dynamic<pkgCache::VerIterator> DynV(ConVersion);
               // duplicate the Conflicts/Breaks/Replaces for :none arch
-              if (D->Version == 0)
-                 NewDepends(Pkg, ConVersion, "", 0, D->Type, OldDepLast);
-              else
-                 NewDepends(Pkg, ConVersion, D.TargetVer(),
-                            D->CompareOp, D->Type, OldDepLast);
+              NewDepends(Pkg, ConVersion, D->Version,
+                    D->CompareOp, D->Type, OldDepLast);
            }
         }
       }
@@ -485,7 +482,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
 
    /* Record the Description (it is not translated) */
    MD5SumValue CurMd5 = List.Description_md5();
-   if (CurMd5.Value().empty() == true)
+   if (CurMd5.Value().empty() == true || List.Description().empty() == true)
       return true;
    std::string CurLang = List.DescriptionLanguage();
 
@@ -560,7 +557,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List)
       Dynamic<pkgCache::VerIterator> DynVer(Ver);
       for (; Ver.end() == false; ++Ver)
       {
-        if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr())
+        if (Ver->Hash == Hash && Version == Ver.VerStr())
         {
            if (List.CollectFileProvides(Cache,Ver) == false)
               return _error->Error(_("Error occurred while processing %s (%s%d)"),
@@ -598,8 +595,11 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
 
    // Insert it into the hash table
    unsigned long const Hash = Cache.Hash(Name);
-   Grp->Next = Cache.HeaderP->GrpHashTable[Hash];
-   Cache.HeaderP->GrpHashTable[Hash] = Group;
+   map_ptrloc *insertAt = &Cache.HeaderP->GrpHashTable[Hash];
+   while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
+      insertAt = &(Cache.GrpP + *insertAt)->Next;
+   Grp->Next = *insertAt;
+   *insertAt = Group;
 
    Grp->ID = Cache.HeaderP->GroupCount++;
    return true;
@@ -628,11 +628,14 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
    // Insert the package into our package list
    if (Grp->FirstPackage == 0) // the group is new
    {
+      Grp->FirstPackage = Package;
       // Insert it into the hash table
       unsigned long const Hash = Cache.Hash(Name);
-      Pkg->NextPackage = Cache.HeaderP->PkgHashTable[Hash];
-      Cache.HeaderP->PkgHashTable[Hash] = Package;
-      Grp->FirstPackage = Package;
+      map_ptrloc *insertAt = &Cache.HeaderP->PkgHashTable[Hash];
+      while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.PkgP + *insertAt)->Name) > 0)
+        insertAt = &(Cache.PkgP + *insertAt)->NextPackage;
+      Pkg->NextPackage = *insertAt;
+      *insertAt = Package;
    }
    else // Group the Packages together
    {
@@ -671,6 +674,7 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G,
    bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
    pkgCache::PkgIterator D = G.PackageList();
    Dynamic<pkgCache::PkgIterator> DynD(D);
+   map_ptrloc const VerStrIdx = V->VerStr;
    for (; D.end() != true; D = G.NextPkg(D))
    {
       if (Arch == D.Arch() || D->VersionList == 0)
@@ -681,16 +685,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G,
       if (coInstall == true)
       {
         // Replaces: ${self}:other ( << ${binary:Version})
-        NewDepends(D, V, V.VerStr(),
+        NewDepends(D, V, VerStrIdx,
                    pkgCache::Dep::Less, pkgCache::Dep::Replaces,
                    OldDepLast);
         // Breaks: ${self}:other (!= ${binary:Version})
-        NewDepends(D, V, V.VerStr(),
+        NewDepends(D, V, VerStrIdx,
                    pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
                    OldDepLast);
       } else {
         // Conflicts: ${self}:other
-        NewDepends(D, V, "",
+        NewDepends(D, V, 0,
                    pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts,
                    OldDepLast);
       }
@@ -707,17 +711,18 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator &V,
    bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
    if (coInstall == true)
    {
+      map_ptrloc const VerStrIdx = V->VerStr;
       // Replaces: ${self}:other ( << ${binary:Version})
-      NewDepends(D, V, V.VerStr(),
+      NewDepends(D, V, VerStrIdx,
                 pkgCache::Dep::Less, pkgCache::Dep::Replaces,
                 OldDepLast);
       // Breaks: ${self}:other (!= ${binary:Version})
-      NewDepends(D, V, V.VerStr(),
+      NewDepends(D, V, VerStrIdx,
                 pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
                 OldDepLast);
    } else {
       // Conflicts: ${self}:other
-      NewDepends(D, V, "",
+      NewDepends(D, V, 0,
                 pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts,
                 OldDepLast);
    }
@@ -763,6 +768,8 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
 /* This puts a version structure in the linked list */
 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
                                            const string &VerStr,
+                                           map_ptrloc const ParentPkg,
+                                           unsigned long const Hash,
                                            unsigned long Next)
 {
    // Get a structure
@@ -774,12 +781,37 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
    Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
    //Dynamic<pkgCache::VerIterator> DynV(Ver); // caller MergeListVersion already takes care of it
    Ver->NextVer = Next;
+   Ver->ParentPkg = ParentPkg;
+   Ver->Hash = Hash;
    Ver->ID = Cache.HeaderP->VersionCount++;
+
+   // try to find the version string in the group for reuse
+   pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+   pkgCache::GrpIterator Grp = Pkg.Group();
+   if (Pkg.end() == false && Grp.end() == false)
+   {
+      for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
+      {
+        if (Pkg == P)
+           continue;
+        for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
+        {
+           int const cmp = strcmp(V.VerStr(), VerStr.c_str());
+           if (cmp == 0)
+           {
+              Ver->VerStr = V->VerStr;
+              return Version;
+           }
+           else if (cmp < 0)
+              break;
+        }
+      }
+   }
+   // haven't found the version string, so create
    map_ptrloc const idxVerStr = WriteStringInMap(VerStr);
    if (unlikely(idxVerStr == 0))
       return 0;
    Ver->VerStr = idxVerStr;
-   
    return Version;
 }
                                                                        /*}}}*/
@@ -833,7 +865,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
    // Fill it in
    Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
    Desc->ID = Cache.HeaderP->DescriptionCount++;
-   map_ptrloc const idxlanguage_code = WriteStringInMap(Lang);
+   map_ptrloc const idxlanguage_code = WriteUniqString(Lang);
    if (unlikely(idxlanguage_code == 0))
       return 0;
    Desc->language_code = idxlanguage_code;
@@ -861,35 +893,49 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
                                   unsigned int const &Op,
                                   unsigned int const &Type,
                                   map_ptrloc* &OldDepLast)
+{
+   map_ptrloc index = 0;
+   if (Version.empty() == false)
+   {
+      int const CmpOp = Op & 0x0F;
+      // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages)
+      if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0)
+        index = Ver->VerStr;
+
+      if (index == 0)
+      {
+        void const * const oldMap = Map.Data();
+        index = WriteStringInMap(Version);
+        if (unlikely(index == 0))
+           return false;
+        if (OldDepLast != 0 && oldMap != Map.Data())
+           OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+      }
+   }
+   return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast);
+}
+bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
+                                  pkgCache::VerIterator &Ver,
+                                  map_ptrloc const Version,
+                                  unsigned int const &Op,
+                                  unsigned int const &Type,
+                                  map_ptrloc* &OldDepLast)
 {
    void const * const oldMap = Map.Data();
    // Get a structure
    map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
    if (unlikely(Dependency == 0))
       return false;
-   
+
    // Fill it in
    pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
    Dynamic<pkgCache::DepIterator> DynDep(Dep);
    Dep->ParentVer = Ver.Index();
    Dep->Type = Type;
    Dep->CompareOp = Op;
+   Dep->Version = Version;
    Dep->ID = Cache.HeaderP->DependsCount++;
 
-   // Probe the reverse dependency list for a version string that matches
-   if (Version.empty() == false)
-   {
-/*      for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
-        if (I->Version != 0 && I.TargetVer() == Version)
-           Dep->Version = I->Version;*/
-      if (Dep->Version == 0) {
-        map_ptrloc const index = WriteStringInMap(Version);
-        if (unlikely(index == 0))
-           return false;
-        Dep->Version = index;
-      }
-   }
-
    // Link it to the package
    Dep->Package = Pkg.Index();
    Dep->NextRevDepends = Pkg->RevDepends;