Browse Source

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
tags/debian/1.1.exp9
David Kalnischkies 6 years ago
parent
commit
bb0f6a34c4
6 changed files with 83 additions and 88 deletions
  1. +5
    -25
      apt-pkg/deb/deblistparser.cc
  2. +69
    -43
      apt-pkg/pkgcachegen.cc
  3. +1
    -4
      apt-pkg/pkgcachegen.h
  4. +4
    -11
      test/integration/test-apt-cache
  5. +1
    -1
      test/integration/test-bug-590041-prefer-non-virtual-packages
  6. +3
    -4
      test/integration/test-multiarch-allowed

+ 5
- 25
apt-pkg/deb/deblistparser.cc View 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(':');

// 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;
}


+ 69
- 43
apt-pkg/pkgcachegen.cc View 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;
}
// 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<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 /*{{{*/


+ 1
- 4
apt-pkg/pkgcachegen.h View File

@@ -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);


+ 4
- 11
test/integration/test-apt-cache View File

@@ -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>


+ 1
- 1
test/integration/test-bug-590041-prefer-non-virtual-packages View File

@@ -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


+ 3
- 4
test/integration/test-multiarch-allowed View File

@@ -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...


Loading…
Cancel
Save