summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2023-12-04 19:49:33 +0000
committerDavid Kalnischkies <david@kalnischkies.de>2023-12-04 23:35:04 +0000
commit0abf584b283e3e0f040b9ec0e7153c6e52291b2a (patch)
treee97833157e694787a53c0a637fe09ecd1ff6c89c
parent4e344a4c1d2862b7cdb900a20222bc22ac5edcf7 (diff)
Have Grp.FindPreferredPkg return very foreign pkgs as last resort
Usually this method will return the package in the most preferred architecture (e.g. native) as that is usually what the user talks about and also information wise for our internal usage the most dense. Early on in parsing Packages files through it can happen that we encounter stanzas about packages in architectures we are not even configured to know about – we have to collect them anyhow as we might be requested to show info about them or they could be in the status file and we can't ignore stanzas in the status file… trouble is that this method used to not return anything if only such an architecture was present if we later discover other architectures which causes Provides and Conflicts which are added lazily on discovery of an architecture to not be added correctly. The result is like in the testcase that apt could be instructed to install a package without respecting its negative dependencies, which is bad even if its discovered by dpkg and refused. It does only happen with unknown architectures through which mostly happens if you are unlucky (amd64 users tend to be very lucky as that sorts early) and use flat-style repositories containing multiple architectures. Reported-By: Tianyu Chen (billchenchina) on IRC
-rw-r--r--apt-pkg/pkgcache.cc20
-rw-r--r--doc/examples/configure-index2
-rwxr-xr-xtest/integration/test-dont-forget-conflicts-via-unknown-architectures43
3 files changed, 59 insertions, 6 deletions
diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc
index 0d18c6cf8..76336b9b3 100644
--- a/apt-pkg/pkgcache.cc
+++ b/apt-pkg/pkgcache.cc
@@ -393,11 +393,17 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &Prefer
pkgCache::PkgIterator Pkg = FindPkg(StringView("native", 6));
if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
return Pkg;
-
- std::vector<std::string> const archs = APT::Configuration::getArchitectures();
- for (std::vector<std::string>::const_iterator a = archs.begin();
- a != archs.end(); ++a) {
- Pkg = FindPkg(*a);
+ // native and foreign
+ for (auto const &a : APT::Configuration::getArchitectures())
+ {
+ Pkg = FindPkg(a);
+ if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
+ return Pkg;
+ }
+ // very foreign/barbarian
+ for (auto const &a : _config->FindVector("APT::BarbarianArchitectures"))
+ {
+ Pkg = FindPkg(a);
if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
return Pkg;
}
@@ -405,6 +411,10 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &Prefer
Pkg = FindPkg(StringView("none", 4));
if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
return Pkg;
+ // the "rest" we somehow know about (+ those we tried already again as skipping is hard)
+ for (Pkg = PackageList(); not Pkg.end(); Pkg = NextPkg(Pkg))
+ if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
+ return Pkg;
if (PreferNonVirtual == true)
return FindPreferredPkg(false);
diff --git a/doc/examples/configure-index b/doc/examples/configure-index
index 6a168192c..0d4dd31a5 100644
--- a/doc/examples/configure-index
+++ b/doc/examples/configure-index
@@ -540,7 +540,7 @@ DPkg
// controls if apt will apport on the first dpkg error or if it
// tries to install as many packages as possible
- StopOnError "true";
+ StopOnError "<BOOL>";
Progress-Fancy {
progress-fg "<STRING>";
diff --git a/test/integration/test-dont-forget-conflicts-via-unknown-architectures b/test/integration/test-dont-forget-conflicts-via-unknown-architectures
new file mode 100755
index 000000000..07d5d8f84
--- /dev/null
+++ b/test/integration/test-dont-forget-conflicts-via-unknown-architectures
@@ -0,0 +1,43 @@
+#!/bin/sh
+set -e
+
+TESTDIR="$(readlink -f "$(dirname "$0")")"
+. "$TESTDIR/framework"
+setupenvironment
+configarchitecture 'arm64'
+configdpkgnoopchroot
+
+buildsimplenativepackage 'pkga' 'arm64' '1' 'stable'
+buildsimplenativepackage 'pkgb' 'arm64' '1' 'stable'
+
+cd aptarchive
+aptftparchive packages ../incoming > Packages
+cd ..
+generatereleasefiles
+signreleasefiles
+setupflataptarchive
+testsuccess apt update
+
+testsuccess apt install pkga pkgb -y
+testdpkginstalled 'pkga' 'pkgb'
+
+rm -rf aptarchive incoming
+
+buildsimplenativepackage 'pkga' 'arm64,amd64' '2' 'unstable' 'Provides: pkgb
+Breaks: pkgb (<< 1+)
+Replaces: pkgb (<< 1+)'
+
+mkdir aptarchive
+cd aptarchive
+aptftparchive packages ../incoming > Packages
+cd ..
+generatereleasefiles
+signreleasefiles
+setupflataptarchive
+testsuccess apt update
+
+#apt upgrade pkga -o Debug::pkgDpkgPm=1 -y -o Dpkg::use-pty=0
+rm -f rootdir/var/cache/apt/*.bin
+testsuccess apt upgrade pkga -y
+testdpkginstalled 'pkga'
+testdpkgnotinstalled 'pkgb'