]> git.saurik.com Git - apt.git/commitdiff
just-in-time creation for (explicit) negative deps
authorDavid Kalnischkies <david@kalnischkies.de>
Fri, 17 Jul 2015 08:53:01 +0000 (10:53 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Mon, 10 Aug 2015 15:27:59 +0000 (17:27 +0200)
Now that we deal with provides in a more dynamic fashion the last
remaining problem is explicit dependencies like 'Conflicts: foo' which
have to apply to all architectures, but creating them all at the same
time requires us to know all architectures ending up in the cache which
isn't needed to be the same set as all foreign architectures.

The effect is visible already now through as this prevents the creation
of a bunch of virtual packages for arch:all packages and as such also
many dependencies, just not very visible if you don't look at the stats…

Git-Dch Ignore

apt-pkg/deb/deblistparser.cc
apt-pkg/pkgcachegen.cc
apt-pkg/pkgcachegen.h
test/integration/test-apt-cache
test/integration/test-bug-590041-prefer-non-virtual-packages
test/integration/test-multiarch-allowed

index 87aa99c6ebd233149493e7376c97a7b6d63209e2..1154016a96320d0bd4033bdddafec613e31dc02d 100644 (file)
@@ -790,43 +790,23 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
         return _error->Error("Problem parsing dependency %s",Tag);
       size_t const found = Package.rfind(':');
 
         return _error->Error("Problem parsing dependency %s",Tag);
       size_t const found = Package.rfind(':');
 
-      // If negative is unspecific it needs to apply on all architectures
-      if (MultiArchEnabled == true && found == string::npos &&
-         (Type == pkgCache::Dep::Conflicts ||
-          Type == pkgCache::Dep::DpkgBreaks ||
-          Type == pkgCache::Dep::Replaces))
+      if (found == string::npos || strcmp(Package.c_str() + found, ":any") == 0)
       {
       {
-        for (std::vector<std::string>::const_iterator a = Architectures.begin();
-             a != Architectures.end(); ++a)
-           if (NewDepends(Ver,Package,*a,Version,Op,Type) == false)
-              return false;
-        if (NewDepends(Ver,Package,"none",Version,Op,Type) == false)
+        if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
            return false;
       }
            return false;
       }
-      else if (found != string::npos &&
-              strcmp(Package.c_str() + found, ":any") != 0)
+      else
       {
         string Arch = Package.substr(found+1, string::npos);
         Package = Package.substr(0, found);
         // Such dependencies are not supposed to be accepted …
       {
         string Arch = Package.substr(found+1, string::npos);
         Package = Package.substr(0, found);
         // Such dependencies are not supposed to be accepted …
-        // … but this is probably the best thing to do.
+        // … but this is probably the best thing to do anyway
         if (Arch == "native")
            Arch = _config->Find("APT::Architecture");
         if (NewDepends(Ver,Package,Arch,Version,Op | pkgCache::Dep::ArchSpecific,Type) == false)
            return false;
       }
         if (Arch == "native")
            Arch = _config->Find("APT::Architecture");
         if (NewDepends(Ver,Package,Arch,Version,Op | pkgCache::Dep::ArchSpecific,Type) == false)
            return false;
       }
-      else
-      {
-        if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
-           return false;
-        if ((Type == pkgCache::Dep::Conflicts ||
-             Type == pkgCache::Dep::DpkgBreaks ||
-             Type == pkgCache::Dep::Replaces) &&
-            NewDepends(Ver, Package,
-                       (pkgArch != "none") ? "none" : _config->Find("APT::Architecture"),
-                       Version,Op,Type) == false)
-           return false;
-      }
+
       if (Start == Stop)
         break;
    }
       if (Start == Stop)
         break;
    }
index c04320555ecdc3f5dd06fffc15e809efe21e520a..26a5e60a6947cca5d95ae812aaac42f9f755fcc2 100644 (file)
@@ -695,6 +695,23 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name
                  if (NewProvides(Ver, Pkg, Ver->VerStr, pkgCache::Flag::MultiArchImplicit) == false)
                     return false;
       }
                  if (NewProvides(Ver, Pkg, Ver->VerStr, pkgCache::Flag::MultiArchImplicit) == false)
                     return false;
       }
+      // and negative dependencies, don't forget negative dependencies
+      {
+        pkgCache::PkgIterator const M = Grp.FindPreferredPkg(false);
+        if (M.end() == false)
+           for (pkgCache::DepIterator Dep = M.RevDependsList(); Dep.end() == false; ++Dep)
+           {
+              if ((Dep->CompareOp & (pkgCache::Dep::ArchSpecific | pkgCache::Dep::MultiArchImplicit)) != 0)
+                 continue;
+              if (Dep->Type != pkgCache::Dep::DpkgBreaks && Dep->Type != pkgCache::Dep::Conflicts &&
+                    Dep->Type != pkgCache::Dep::Replaces)
+                 continue;
+              pkgCache::VerIterator Ver = Dep.ParentVer();
+              map_pointer_t * unused = NULL;
+              if (NewDepends(Pkg, Ver, Dep->Version, Dep->CompareOp, Dep->Type, unused) == false)
+                 return false;
+           }
+      }
 
       // this package is the new last package
       pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage);
 
       // this package is the new last package
       pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage);
@@ -933,33 +950,6 @@ map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
 // ---------------------------------------------------------------------
 /* This creates a dependency element in the tree. It is linked to the
    version and to the package that it is pointing to. */
 // ---------------------------------------------------------------------
 /* This creates a dependency element in the tree. It is linked to the
    version and to the package that it is pointing to. */
-bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
-                                  pkgCache::VerIterator &Ver,
-                                  string const &Version,
-                                  uint8_t const Op,
-                                  uint8_t const Type,
-                                  map_stringitem_t* &OldDepLast)
-{
-   map_stringitem_t 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 = StoreString(VERSIONNUMBER, Version);
-        if (unlikely(index == 0))
-           return false;
-        if (OldDepLast != 0 && oldMap != Map.Data())
-           OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
-      }
-   }
-   return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast);
-}
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
                                   pkgCache::VerIterator &Ver,
                                   map_pointer_t const Version,
 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
                                   pkgCache::VerIterator &Ver,
                                   map_pointer_t const Version,
@@ -1071,28 +1061,64 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
    if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
       return false;
 
    if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
       return false;
 
-   // Locate the target package
-   pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch);
-   // we don't create 'none' packages and their dependencies if we can avoid it …
-   if (Pkg.end() == true && Arch == "none" && strcmp(Ver.ParentPkg().Arch(), "none") != 0)
-      return true;
-   Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
-   if (Pkg.end() == true) {
-      if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
-        return false;
-   }
-
    // Is it a file dependency?
    if (unlikely(PackageName[0] == '/'))
       FoundFileDeps = true;
 
    // Is it a file dependency?
    if (unlikely(PackageName[0] == '/'))
       FoundFileDeps = true;
 
-   /* Caching the old end point speeds up generation substantially */
-   if (OldDepVer != Ver) {
-      OldDepLast = NULL;
-      OldDepVer = Ver;
+   map_stringitem_t idxVersion = 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)
+        idxVersion = Ver->VerStr;
+
+      if (idxVersion == 0)
+      {
+        idxVersion = StoreString(VERSIONNUMBER, Version);
+        if (unlikely(idxVersion == 0))
+           return false;
+      }
+   }
+
+   bool const isNegative = (Type == pkgCache::Dep::DpkgBreaks ||
+        Type == pkgCache::Dep::Conflicts ||
+        Type == pkgCache::Dep::Replaces);
+
+   pkgCache::PkgIterator Pkg;
+   Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
+   if (isNegative == false || (Op & pkgCache::Dep::ArchSpecific) == pkgCache::Dep::ArchSpecific || Grp->FirstPackage == 0)
+   {
+      // Locate the target package
+      Pkg = Grp.FindPkg(Arch);
+      if (Pkg.end() == true) {
+        if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
+           return false;
+      }
+
+      /* Caching the old end point speeds up generation substantially */
+      if (OldDepVer != Ver) {
+        OldDepLast = NULL;
+        OldDepVer = Ver;
+      }
+
+      return Owner->NewDepends(Pkg, Ver, idxVersion, Op, Type, OldDepLast);
    }
    }
+   else
+   {
+      /* Caching the old end point speeds up generation substantially */
+      if (OldDepVer != Ver) {
+        OldDepLast = NULL;
+        OldDepVer = Ver;
+      }
 
 
-   return Owner->NewDepends(Pkg, Ver, Version, Op, Type, OldDepLast);
+      for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
+      {
+        if (Owner->NewDepends(Pkg, Ver, idxVersion, Op, Type, OldDepLast) == false)
+              return false;
+      }
+   }
+   return true;
 }
                                                                        /*}}}*/
 // ListParser::NewProvides - Create a Provides element                 /*{{{*/
 }
                                                                        /*}}}*/
 // ListParser::NewProvides - Create a Provides element                 /*{{{*/
index 34dc6feada3c8df0c27287fc225cf6d8b154109e..0d0fb893f82841d1b2a25ab27c69f837ede60b68 100644 (file)
@@ -76,14 +76,11 @@ class APT_HIDDEN pkgCacheGenerator                                  /*{{{*/
 
    // Flag file dependencies
    bool FoundFileDeps;
 
    // Flag file dependencies
    bool FoundFileDeps;
-   
+
    bool NewGroup(pkgCache::GrpIterator &Grp,const std::string &Name);
    bool NewPackage(pkgCache::PkgIterator &Pkg,const std::string &Name, const std::string &Arch);
    bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
    bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
    bool NewGroup(pkgCache::GrpIterator &Grp,const std::string &Name);
    bool NewPackage(pkgCache::PkgIterator &Pkg,const std::string &Name, const std::string &Arch);
    bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
    bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
-   bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
-                  std::string const &Version, uint8_t const Op,
-                  uint8_t const Type, map_pointer_t* &OldDepLast);
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
                   map_pointer_t const Version, uint8_t const Op,
                   uint8_t const Type, map_pointer_t* &OldDepLast);
    bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver,
                   map_pointer_t const Version, uint8_t const Op,
                   uint8_t const Type, map_pointer_t* &OldDepLast);
index a8ddfd88936c87c0190c4d7f855a6650f8362136..1d90eed5cb280ecc6638fd6e76b7b8a7b2315633 100755 (executable)
@@ -66,7 +66,6 @@ testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
-  Conflicts: <foobar:i386>
  |Recommends: <cool>
   Recommends: <cooler>' aptcache depends foo --implicit
 testsuccessequal 'foo
  |Recommends: <cool>
   Recommends: <cooler>' aptcache depends foo --implicit
 testsuccessequal 'foo
@@ -76,7 +75,6 @@ testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
-  Conflicts: <foobar:i386>
   Recommends: <cool>' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 --implicit
 testsuccessequal 'foo
   Depends: bar
   Recommends: <cool>' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 --implicit
 testsuccessequal 'foo
   Depends: bar
@@ -86,7 +84,6 @@ testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
-  Conflicts: <foobar:i386>
  |Recommends: <cool> (>= 2)
   Recommends: <cooler> (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 --implicit
 testsuccessequal 'foo
  |Recommends: <cool> (>= 2)
   Recommends: <cooler> (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 --implicit
 testsuccessequal 'foo
@@ -94,15 +91,13 @@ testsuccessequal 'foo
   Conflicts: <foobar>' aptcache depends foo --no-recommends
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>' aptcache depends foo --no-recommends
 testsuccessequal 'foo
   Depends: bar
-  Conflicts: <foobar>
-  Conflicts: <foobar:i386>' aptcache depends foo --no-recommends --implicit
+  Conflicts: <foobar>' aptcache depends foo --no-recommends --implicit
 testsuccessequal 'foo
   Depends: bar' aptcache depends foo --important --implicit
 testsuccessequal 'foo
   Conflicts: <foobar>' aptcache depends foo --important --no-depends --conflicts
 testsuccessequal 'foo
 testsuccessequal 'foo
   Depends: bar' aptcache depends foo --important --implicit
 testsuccessequal 'foo
   Conflicts: <foobar>' aptcache depends foo --important --no-depends --conflicts
 testsuccessequal 'foo
-  Conflicts: <foobar>
-  Conflicts: <foobar:i386>' aptcache depends foo --important --no-depends --conflicts --implicit
+  Conflicts: <foobar>' aptcache depends foo --important --no-depends --conflicts --implicit
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
@@ -118,17 +113,15 @@ bar
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
 testsuccessequal 'foo
   Depends: bar
   Conflicts: <foobar>
-  Conflicts: <foobar:i386>
  |Recommends: <cool>
   Recommends: <cooler>
 bar
   Depends: bar
   Breaks: foo
  |Recommends: <cool>
   Recommends: <cooler>
 bar
   Depends: bar
   Breaks: foo
-  Breaks: <foo:i386>
   Replaces: foo
   Replaces: foo
+  Breaks: <foo:i386>
   Replaces: <foo:i386>
 <foobar>
   Replaces: <foo:i386>
 <foobar>
-<foobar:i386>
 <cool>
 <cooler>
 <foo:i386>' aptcache depends foo --recurse --implicit
 <cool>
 <cooler>
 <foo:i386>' aptcache depends foo --recurse --implicit
@@ -151,8 +144,8 @@ testsuccessequal 'bar
 testsuccessequal 'bar
   Depends: bar
   Breaks: foo
 testsuccessequal 'bar
   Depends: bar
   Breaks: foo
-  Breaks: <foo:i386>
   Replaces: foo
   Replaces: foo
+  Breaks: <foo:i386>
   Replaces: <foo:i386>' aptcache depends bar --implicit
 testsuccessequal 'specific
   Depends: <bar:i386>
   Replaces: <foo:i386>' aptcache depends bar --implicit
 testsuccessequal 'specific
   Depends: <bar:i386>
index 3bd7d436ecbc95927dee47fcb51302d4c847c7d0..4e2a5142c9cbba0cc025ec252df533f44fc144e0 100755 (executable)
@@ -45,7 +45,7 @@ EOF
 
 setupaptarchive
 
 
 setupaptarchive
 
-testshowvirtual libc6:i386
+testnopackage libc6:i386
 testsuccessequal "$pkglibc6" aptcache show libc6:armel
 testsuccessequal "$pkglibc6" aptcache show libc6
 testsuccessequal "$pkglibdb1" aptcache show libdb1:i386
 testsuccessequal "$pkglibc6" aptcache show libc6:armel
 testsuccessequal "$pkglibc6" aptcache show libc6
 testsuccessequal "$pkglibdb1" aptcache show libdb1:i386
index a643cd2dc2958e487b29ec902e6df61bb9e4af35..2c791ca19659999c86992c54c16af7629e25beb2 100755 (executable)
@@ -138,10 +138,8 @@ solveableinsinglearch2() {
 The following packages have unmet dependencies:
  hatesfoo : Conflicts: foo but 1 is to be installed
 E: Unable to correct problems, you have held broken packages." aptget install foo hatesfoo -s
 The following packages have unmet dependencies:
  hatesfoo : Conflicts: foo but 1 is to be installed
 E: Unable to correct problems, you have held broken packages." aptget install foo hatesfoo -s
-       testfailureequal "$BADPREFIX
-The following packages have unmet dependencies:
- hatesfooany : Conflicts: foo:any
-E: Unable to correct problems, you have held broken packages." aptget install foo hatesfooany -s
+       # the message differs slightly between single and multiarch
+       testfailuremsg 'E: Unable to correct problems, you have held broken packages.' aptget install foo hatesfooany -s
        testfailureequal "$BADPREFIX
 The following packages have unmet dependencies:
  hatesfoonative : Conflicts: foo but 1 is to be installed
        testfailureequal "$BADPREFIX
 The following packages have unmet dependencies:
  hatesfoonative : Conflicts: foo but 1 is to be installed
@@ -155,6 +153,7 @@ E: Unable to correct problems, you have held broken packages." aptget install fo
 testfailureequal "$BADPREFIX
 The following packages have unmet dependencies:
  hatesfooany : Conflicts: foo:any
 testfailureequal "$BADPREFIX
 The following packages have unmet dependencies:
  hatesfooany : Conflicts: foo:any
+               Conflicts: foo:any:i386
 E: Unable to correct problems, you have held broken packages." aptget install foo:i386 hatesfooany -s
 testsuccessequal 'Reading package lists...
 Building dependency tree...
 E: Unable to correct problems, you have held broken packages." aptget install foo:i386 hatesfooany -s
 testsuccessequal 'Reading package lists...
 Building dependency tree...