summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2015-07-17 10:53:01 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2015-08-10 17:27:59 +0200
commitbb0f6a34c4cebea7884de828c011dc85765ff820 (patch)
tree809a630ba606bac6b9050c97f9ecbccc7562244f
parentecc138f858fab61e0b888d3d13854d1422c3432b (diff)
just-in-time creation for (explicit) negative deps
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
-rw-r--r--apt-pkg/deb/deblistparser.cc30
-rw-r--r--apt-pkg/pkgcachegen.cc112
-rw-r--r--apt-pkg/pkgcachegen.h5
-rwxr-xr-xtest/integration/test-apt-cache15
-rwxr-xr-xtest/integration/test-bug-590041-prefer-non-virtual-packages2
-rwxr-xr-xtest/integration/test-multiarch-allowed7
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<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;
}
- 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);
@@ -935,33 +952,6 @@ map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
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,
uint8_t const Op,
uint8_t const Type,
@@ -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<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;
- /* 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 /*{{{*/
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,15 +76,12 @@ 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);
map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,map_pointer_t const Next) APT_DEPRECATED
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: <foobar>
- Conflicts: <foobar:i386>
|Recommends: <cool>
Recommends: <cooler>' aptcache depends foo --implicit
testsuccessequal 'foo
@@ -76,7 +75,6 @@ testsuccessequal 'foo
testsuccessequal 'foo
Depends: bar
Conflicts: <foobar>
- Conflicts: <foobar:i386>
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>
- Conflicts: <foobar:i386>
|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>
- 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
- 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>
@@ -118,17 +113,15 @@ bar
testsuccessequal 'foo
Depends: bar
Conflicts: <foobar>
- Conflicts: <foobar:i386>
|Recommends: <cool>
Recommends: <cooler>
bar
Depends: bar
Breaks: foo
- Breaks: <foo:i386>
Replaces: foo
+ Breaks: <foo:i386>
Replaces: <foo:i386>
<foobar>
-<foobar:i386>
<cool>
<cooler>
<foo:i386>' aptcache depends foo --recurse --implicit
@@ -151,8 +144,8 @@ testsuccessequal 'bar
testsuccessequal 'bar
Depends: bar
Breaks: foo
- Breaks: <foo:i386>
Replaces: foo
+ Breaks: <foo:i386>
Replaces: <foo:i386>' aptcache depends bar --implicit
testsuccessequal 'specific
Depends: <bar:i386>
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...