summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/depcache.cc91
-rw-r--r--apt-pkg/pkgcache.h2
-rw-r--r--debian/changelog4
-rwxr-xr-xtest/integration/test-multiarch-foreign128
4 files changed, 195 insertions, 30 deletions
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 <apt-pkg/pkgsystem.h>
#include <apt-pkg/tagfile.h>
#include <apt-pkg/progress.h>
+#include <apt-pkg/cacheset.h>
+#include <algorithm>
#include <iostream>
#include <sstream>
#include <set>
@@ -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<std::string> archs = APT::Configuration::getArchitectures();
+ for (std::vector<std::string>::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<Version *> 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<Version *> 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 <kalnischkies@gmail.com> Fri, 11 Nov 2011 15:55:13 +0100
+ -- David Kalnischkies <kalnischkies@gmail.com> 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