From 2b5c35c7bb915dbd46fefd7c79f05364ba22f93b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 23 Nov 2011 00:49:45 +0100 Subject: * apt-pkg/depcache.cc: - prefer native providers over foreigns even if the chain is foreign The code preferred real over virtual packages and based on priorities. This is changed in so far that a real package from any arch is preferred over any virtual provider and if priorities doesn't help in choosing the best provider we choose it based on architectures --- apt-pkg/depcache.cc | 91 ++++++++++++++++------- apt-pkg/pkgcache.h | 2 +- debian/changelog | 4 +- test/integration/test-multiarch-foreign | 128 ++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 30 deletions(-) create mode 100755 test/integration/test-multiarch-foreign diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 529e9240d..031fca5c0 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -23,7 +23,9 @@ #include #include #include +#include +#include #include #include #include @@ -940,6 +942,51 @@ bool pkgDepCache::IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, // DepCache::MarkInstall - Put the package in the install state /*{{{*/ // --------------------------------------------------------------------- /* */ +struct CompareProviders { + pkgCache::PkgIterator const Pkg; + CompareProviders(pkgCache::DepIterator const &Dep) : Pkg(Dep.TargetPkg()) {}; + //bool operator() (APT::VersionList::iterator const &AV, APT::VersionList::iterator const &BV) + bool operator() (pkgCache::VerIterator const &AV, pkgCache::VerIterator const &BV) + { + pkgCache::PkgIterator const A = AV.ParentPkg(); + pkgCache::PkgIterator const B = BV.ParentPkg(); + // Prefer packages in the same group as the target; e.g. foo:i386, foo:amd64 + if (A->Group != B->Group) + { + if (A->Group == Pkg->Group && B->Group != Pkg->Group) + return false; + else if (B->Group == Pkg->Group && A->Group != Pkg->Group) + return true; + } + // we like essentials + if ((A->Flags & pkgCache::Flag::Essential) != (B->Flags & pkgCache::Flag::Essential)) + { + if ((A->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + return false; + else if ((B->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + return true; + } + // higher priority seems like a good idea + if (AV->Priority != BV->Priority) + return AV->Priority < BV->Priority; + // prefer native architecture + if (strcmp(A.Arch(), B.Arch()) != 0) + { + if (strcmp(A.Arch(), A.Cache()->NativeArch()) == 0) + return false; + else if (strcmp(B.Arch(), B.Cache()->NativeArch()) == 0) + return true; + std::vector archs = APT::Configuration::getArchitectures(); + for (std::vector::const_iterator a = archs.begin(); a != archs.end(); ++a) + if (*a == A.Arch()) + return false; + else if (*a == B.Arch()) + return true; + } + // unable to decideā€¦ + return A->ID < B->ID; + } +}; bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, unsigned long Depth, bool FromUser, bool ForceImportantDeps) @@ -1102,41 +1149,28 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, /* This bit is for processing the possibilty of an install/upgrade fixing the problem */ - SPtrArray List = Start.AllTargets(); if (Start->Type != Dep::DpkgBreaks && (DepState[Start->ID] & DepCVer) == DepCVer) { - // Right, find the best version to install.. - Version **Cur = List; - PkgIterator P = Start.TargetPkg(); - PkgIterator InstPkg(*Cache,0); - - // See if there are direct matches (at the start of the list) - for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++) + APT::VersionList verlist; + pkgCache::VerIterator Cand = PkgState[Start.TargetPkg()->ID].CandidateVerIter(*this); + if (Cand.end() == false && VS().CheckDep(Cand.VerStr(), Start->CompareOp, Start.TargetVer()) == true) + verlist.insert(Cand); + for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv) { - PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg); - if (PkgState[Pkg->ID].CandidateVer != *Cur) + pkgCache::VerIterator V = Prv.OwnerVer(); + pkgCache::VerIterator Cand = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this); + if (Cand.end() == true || V != Cand || + VS().CheckDep(Cand.VerStr(), Start->CompareOp, Start.TargetVer()) == false) continue; - InstPkg = Pkg; - break; + verlist.insert(Cand); } + CompareProviders comp(Start); + APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp); - // Select the highest priority providing package - if (InstPkg.end() == true) - { - pkgPrioSortList(*Cache,Cur); - for (; *Cur != 0; Cur++) - { - PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg); - if (PkgState[Pkg->ID].CandidateVer != *Cur) - continue; - InstPkg = Pkg; - break; - } - } - - if (InstPkg.end() == false) + if (InstVer != verlist.end()) { + pkgCache::PkgIterator InstPkg = InstVer.ParentPkg(); if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name() << " as " << Start.DepType() << " of " << Pkg.Name() @@ -1154,7 +1188,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, // mark automatic dependency MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps); // Set the autoflag, after MarkInstall because MarkInstall unsets it - if (P->CurrentVer == 0) + if (InstPkg->CurrentVer == 0) PkgState[InstPkg->ID].Flags |= Flag::Auto; } } @@ -1166,6 +1200,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, upgrade the package. */ if (Start.IsNegative() == true) { + SPtrArray List = Start.AllTargets(); for (Version **I = List; *I != 0; I++) { VerIterator Ver(*this,*I); diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 7e32a3a96..fd1a02149 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -198,6 +198,7 @@ class pkgCache /*{{{*/ inline PkgFileIterator FileEnd(); inline bool MultiArchCache() const { return MultiArchEnabled; }; + inline char const * const NativeArch() const; // Make me a function pkgVersioningSystem *VS; @@ -213,7 +214,6 @@ class pkgCache /*{{{*/ private: bool MultiArchEnabled; PkgIterator SingleArchFindPkg(const std::string &Name); - inline char const * const NativeArch() const; }; /*}}}*/ // Header structure /*{{{*/ diff --git a/debian/changelog b/debian/changelog index 058e2926e..0a66d2579 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,8 +16,10 @@ apt (0.8.16~exp8) experimental; urgency=low * cmdline/apt-{get,cache,mark}.cc: - use Lists instead of Sets if input order should be preserved for commands accepting lists of packages, e.g. policy (Closes: #625960) + * apt-pkg/depcache.cc: + - prefer native providers over foreigns even if the chain is foreign - -- David Kalnischkies Fri, 11 Nov 2011 15:55:13 +0100 + -- David Kalnischkies Wed, 23 Nov 2011 00:18:35 +0100 apt (0.8.16~exp7) experimental; urgency=low diff --git a/test/integration/test-multiarch-foreign b/test/integration/test-multiarch-foreign new file mode 100755 index 000000000..d0ad829a7 --- /dev/null +++ b/test/integration/test-multiarch-foreign @@ -0,0 +1,128 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' 'i386' 'armel' + +insertpackage 'unstable' 'cool-foo' 'amd64,i386' '1.0' 'Depends: foo' +insertpackage 'unstable' 'foo' 'amd64,i386,armel' '1.0' 'Multi-Arch: foreign' + +insertpackage 'unstable' 'cool-bar' 'amd64,i386' '1.0' 'Depends: bar-provider' +insertpackage 'unstable' 'bar' 'amd64,i386,armel' '1.0' 'Provides: bar-provider +Multi-Arch: foreign' + +setupaptarchive + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo +The following NEW packages will be installed: + cool-foo:i386 foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [amd64]) +Inst cool-foo:i386 (1.0 unstable [i386]) +Conf foo (1.0 unstable [amd64]) +Conf cool-foo:i386 (1.0 unstable [i386])' aptget install cool-foo:i386 -s + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo +The following NEW packages will be installed: + cool-foo foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [amd64]) +Inst cool-foo (1.0 unstable [amd64]) +Conf foo (1.0 unstable [amd64]) +Conf cool-foo (1.0 unstable [amd64])' aptget install cool-foo:amd64 -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + cool-foo foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1.0 unstable [amd64]) +Inst cool-foo (1.0 unstable [amd64]) +Conf foo (1.0 unstable [amd64]) +Conf cool-foo (1.0 unstable [amd64])' aptget install cool-foo:amd64 foo:amd64 -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + cool-foo foo:i386 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo:i386 (1.0 unstable [i386]) +Inst cool-foo (1.0 unstable [amd64]) +Conf foo:i386 (1.0 unstable [i386]) +Conf cool-foo (1.0 unstable [amd64])' aptget install cool-foo:amd64 foo:i386 -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + cool-foo foo:armel +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo:armel (1.0 unstable [armel]) +Inst cool-foo (1.0 unstable [amd64]) +Conf foo:armel (1.0 unstable [armel]) +Conf cool-foo (1.0 unstable [amd64])' aptget install cool-foo:amd64 foo:armel -s + + + + + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + bar +The following NEW packages will be installed: + bar cool-bar:i386 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1.0 unstable [amd64]) +Inst cool-bar:i386 (1.0 unstable [i386]) +Conf bar (1.0 unstable [amd64]) +Conf cool-bar:i386 (1.0 unstable [i386])' aptget install cool-bar:i386 -s + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + bar +The following NEW packages will be installed: + bar cool-bar +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1.0 unstable [amd64]) +Inst cool-bar (1.0 unstable [amd64]) +Conf bar (1.0 unstable [amd64]) +Conf cool-bar (1.0 unstable [amd64])' aptget install cool-bar:amd64 -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar cool-bar +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1.0 unstable [amd64]) +Inst cool-bar (1.0 unstable [amd64]) +Conf bar (1.0 unstable [amd64]) +Conf cool-bar (1.0 unstable [amd64])' aptget install cool-bar:amd64 bar:amd64 -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar:i386 cool-bar +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar:i386 (1.0 unstable [i386]) +Inst cool-bar (1.0 unstable [amd64]) +Conf bar:i386 (1.0 unstable [i386]) +Conf cool-bar (1.0 unstable [amd64])' aptget install cool-bar:amd64 bar:i386 -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar:armel cool-bar +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar:armel (1.0 unstable [armel]) +Inst cool-bar (1.0 unstable [amd64]) +Conf bar:armel (1.0 unstable [armel]) +Conf cool-bar (1.0 unstable [amd64])' aptget install cool-bar:amd64 bar:armel -s -- cgit v1.2.3