From bb0f6a34c4cebea7884de828c011dc85765ff820 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 17 Jul 2015 10:53:01 +0200 Subject: just-in-time creation for (explicit) negative deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 | 30 +----- apt-pkg/pkgcachegen.cc | 112 +++++++++++++-------- apt-pkg/pkgcachegen.h | 5 +- test/integration/test-apt-cache | 15 +-- .../test-bug-590041-prefer-non-virtual-packages | 2 +- test/integration/test-multiarch-allowed | 7 +- 6 files changed, 83 insertions(+), 88 deletions(-) diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 87aa99c6e..1154016a9 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -790,43 +790,23 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, 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::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; } - 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 … - // … 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; } - 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; } diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index c04320555..26a5e60a6 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -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; } + // 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); @@ -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. */ -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, @@ -1071,28 +1061,64 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, 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 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; - /* 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 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 /*{{{*/ diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 34dc6fead..0d0fb893f 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -76,14 +76,11 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ // 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 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); diff --git a/test/integration/test-apt-cache b/test/integration/test-apt-cache index a8ddfd889..1d90eed5c 100755 --- a/test/integration/test-apt-cache +++ b/test/integration/test-apt-cache @@ -66,7 +66,6 @@ testsuccessequal 'foo testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: |Recommends: Recommends: ' aptcache depends foo --implicit testsuccessequal 'foo @@ -76,7 +75,6 @@ testsuccessequal 'foo testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: Recommends: ' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 --implicit testsuccessequal 'foo Depends: bar @@ -86,7 +84,6 @@ testsuccessequal 'foo testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: |Recommends: (>= 2) Recommends: (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 --implicit testsuccessequal 'foo @@ -94,15 +91,13 @@ testsuccessequal 'foo Conflicts: ' aptcache depends foo --no-recommends testsuccessequal 'foo Depends: bar - Conflicts: - Conflicts: ' aptcache depends foo --no-recommends --implicit + Conflicts: ' aptcache depends foo --no-recommends --implicit testsuccessequal 'foo Depends: bar' aptcache depends foo --important --implicit testsuccessequal 'foo Conflicts: ' aptcache depends foo --important --no-depends --conflicts testsuccessequal 'foo - Conflicts: - Conflicts: ' aptcache depends foo --important --no-depends --conflicts --implicit + Conflicts: ' aptcache depends foo --important --no-depends --conflicts --implicit testsuccessequal 'foo Depends: bar Conflicts: @@ -118,17 +113,15 @@ bar testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: |Recommends: Recommends: bar Depends: bar Breaks: foo - Breaks: Replaces: foo + Breaks: Replaces: - ' aptcache depends foo --recurse --implicit @@ -151,8 +144,8 @@ testsuccessequal 'bar testsuccessequal 'bar Depends: bar Breaks: foo - Breaks: Replaces: foo + Breaks: Replaces: ' aptcache depends bar --implicit testsuccessequal 'specific Depends: diff --git a/test/integration/test-bug-590041-prefer-non-virtual-packages b/test/integration/test-bug-590041-prefer-non-virtual-packages index 3bd7d436e..4e2a5142c 100755 --- a/test/integration/test-bug-590041-prefer-non-virtual-packages +++ b/test/integration/test-bug-590041-prefer-non-virtual-packages @@ -45,7 +45,7 @@ EOF setupaptarchive -testshowvirtual libc6:i386 +testnopackage libc6:i386 testsuccessequal "$pkglibc6" aptcache show libc6:armel testsuccessequal "$pkglibc6" aptcache show libc6 testsuccessequal "$pkglibdb1" aptcache show libdb1:i386 diff --git a/test/integration/test-multiarch-allowed b/test/integration/test-multiarch-allowed index a643cd2dc..2c791ca19 100755 --- a/test/integration/test-multiarch-allowed +++ b/test/integration/test-multiarch-allowed @@ -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 - 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 @@ -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 + 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... -- cgit v1.2.3