diff options
author | Julian Andres Klode <julian.klode@canonical.com> | 2018-12-03 17:18:18 +0100 |
---|---|---|
committer | Julian Andres Klode <julian.klode@canonical.com> | 2019-03-01 11:40:29 +0000 |
commit | 54e1ee73059bbad881908028abce574039ec77b9 (patch) | |
tree | b54d002035e1cf71499221288028a99d6f6a86b9 | |
parent | dd05bdac89acbe96103b0f0ca488c9aba106d1ee (diff) |
Introduce experimental 'never' pinning for sources
This allows disabling a repository by pinning it to 'never',
which is internally translated to a value of -32768 (or whatever
the minimum of short is).
This overrides any other pin for that repository. It can be used
to make sure certain sources are never used; for example, in
unattended-upgrades.
To prevent semantic changes to existing files, we substitute
min + 1 for every pin-priority: <min>. This is a temporary
solution, as we are waiting for an ABI break.
To add pins with that value, the special Pin-Priority
"never" may be used for now. It's unclear if that will
persist, or if the interface will change eventually.
(similar to commit 8bb2a91a070170d7d8e71206d1c66a26809bdbc3)
LP: #1814727
-rw-r--r-- | apt-pkg/policy.cc | 44 | ||||
-rw-r--r-- | test/integration/framework | 13 | ||||
-rwxr-xr-x | test/integration/test-policy-pinning | 105 |
3 files changed, 159 insertions, 3 deletions
diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 3cfc32829..a44bd7efe 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -18,7 +18,8 @@ 500 = Default package files 100 = The status file and ButAutomaticUpgrades sources 0 -> 100 = NotAutomatic sources like experimental - -inf -> 0 = Never selected + -inf -> 0 = Never selected + –32768 = Never selected, overrides everything else ##################################################################### */ /*}}}*/ @@ -50,6 +51,8 @@ using namespace std; +static const short NEVER_PIN = std::numeric_limits<short>::min(); + // Policy::Init - Startup and bind to a cache /*{{{*/ // --------------------------------------------------------------------- /* Set the defaults for operation. The default mode with no loaded policy @@ -115,7 +118,7 @@ bool pkgPolicy::InitDefaults() pkgVersionMatch Match(I->Data,I->Type); for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) { - if (Match.FileMatch(F) == true && Fixed[F->ID] == false) + if (Match.FileMatch(F) == true && (Fixed[F->ID] == false || I->Priority == NEVER_PIN)) { if (I->Priority != 0 && I->Priority > 0) Cur = I->Priority; @@ -162,6 +165,24 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk if (Max < 0) return Pkg.CurrentVer(); + // If the package specific-pin refers to a version that is only available from + // never sources, ignore it. + if (!Pref.end()) + { + bool AllNever = true; + for (pkgCache::VerFileIterator VF = Pref.FileList(); VF.end() == false; ++VF) + { + if ((VF.File()->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource) + continue; + + if (PFPriority[VF.File()->ID] != NEVER_PIN) + AllNever = false; + } + + if (AllNever) + Pref = pkgCache::VerIterator(*Pkg.Cache()); + } + /* Falling through to the default version.. Setting Max to zero effectively excludes everything <= 0 which are the non-automatic priorities.. The status file is given a prio of 100 which will exclude @@ -194,7 +215,12 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk instVer == false) continue; + signed Prio = PFPriority[VF.File()->ID]; + + // A package file pinned to NEVER_PIN can never be a candidate. + if (Prio == NEVER_PIN && instVer == false) + continue; if (Prio > Max) { Pref = Ver; @@ -446,7 +472,19 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) } for (; Word != End && isspace(*Word) != 0; Word++); - short int priority = Tags.FindI("Pin-Priority", 0); + std::string sPriority = Tags.FindS("Pin-Priority"); + short int priority = sPriority == "never" ? NEVER_PIN : Tags.FindI("Pin-Priority", 0); + + if (sPriority == "never" && not Name.empty()) + return _error->Error(_("%s: The special 'Pin-Priority: %s' can only be used for 'Package: *' records"), File.c_str(), "never"); + + // Silently clamp the never pin to never pin + 1 + if (priority == NEVER_PIN && sPriority != "never") + priority = NEVER_PIN + 1; + + if (priority == 0 && Tags.FindS("Pin-Priority") == "never") { + priority = NEVER_PIN; + } if (priority == 0) { _error->Warning(_("No priority (or zero) specified for pin")); diff --git a/test/integration/framework b/test/integration/framework index 62d3a8386..38f08a59b 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1148,6 +1148,19 @@ testfailure() { fi } +testsuccessequal() { + local CMP="$1" + shift + testsuccess "$@" + testfileequal "${TMPWORKINGDIRECTORY}/rootdir/tmp/testsuccess.output" "$CMP" +} +testfailureequal() { + local CMP="$1" + shift + testfailure "$@" + testfileequal "${TMPWORKINGDIRECTORY}/rootdir/tmp/testfailure.output" "$CMP" +} + testwebserverlaststatuscode() { local DOWNLOG='rootdir/tmp/webserverstatus-testfile.log' local STATUS='rootdir/tmp/webserverstatus-statusfile.log' diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index 8eb4bcbad..6ee39077a 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -12,6 +12,7 @@ setupflataptarchive STATUS=$(readlink -f rootdir/var/lib/dpkg/status) APTARCHIVE=$(readlink -f aptarchive) +tmppath=$(readlink -f .) testequalpolicy() { local SP="$1" @@ -261,3 +262,107 @@ aptgetupdate testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 500 0 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 990 0 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t stable testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 990 500 0 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t backports + + + +msgmsg "Check that short-max/min is a valid pin" +currentpin() { +echo "Package: * +Pin: release n=backports +Pin-Priority: $1 +" > rootdir/etc/apt/preferences +testsuccessequal "coolstuff: + Installed: 2.0~bpo1 + Candidate: ${2} + Version table: + 2.0~bpo2 0 + ${3:-$1} file:${tmppath}/aptarchive/ backports/main i386 Packages + *** 2.0~bpo1 0 + 100 ${tmppath}/rootdir/var/lib/dpkg/status + 1.0 0 + 500 file:${tmppath}/aptarchive/ stable/main i386 Packages" aptcache policy coolstuff +} + +currentpin '32767' '2.0~bpo2' +currentpin '-32768' '2.0~bpo1' '-32767' +currentpin '-32767' '2.0~bpo1' '-32767' + + +msgmsg "Check for override pins" + +msgmsg "Normal pins: First one wins" +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: 990 + +Package: coolstuff +Pin: release n=backports +Pin-Priority: 991 +" > rootdir/etc/apt/preferences +testsuccessequal "coolstuff: + Installed: 2.0~bpo1 + Candidate: 2.0~bpo2 + Package pin: 2.0~bpo2 + Version table: + 2.0~bpo2 990 + 100 file:${tmppath}/aptarchive/ backports/main i386 Packages + *** 2.0~bpo1 990 + 100 ${tmppath}/rootdir/var/lib/dpkg/status + 1.0 990 + 500 file:${tmppath}/aptarchive/ stable/main i386 Packages" aptcache policy coolstuff + +msgmsg "Never pins: Never wins over package-specific" +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: 990 + +Package: * +Pin: release n=backports +Pin-Priority: never +" > rootdir/etc/apt/preferences + +testsuccessequal "coolstuff: + Installed: 2.0~bpo1 + Candidate: 2.0~bpo1 + Package pin: 2.0~bpo2 + Version table: + 2.0~bpo2 990 + -32768 file:${tmppath}/aptarchive/ backports/main i386 Packages + *** 2.0~bpo1 990 + 100 ${tmppath}/rootdir/var/lib/dpkg/status + 1.0 990 + 500 file:${tmppath}/aptarchive/ stable/main i386 Packages" aptcache policy coolstuff + +msgmsg "Never pins: Never wins over other" +echo "Package: * +Pin: release n=backports +Pin-Priority: 990 + +Package: * +Pin: release n=backports +Pin-Priority: never +" > rootdir/etc/apt/preferences + +testsuccessequal "coolstuff: + Installed: 2.0~bpo1 + Candidate: 2.0~bpo1 + Version table: + 2.0~bpo2 0 + -32768 file:${tmppath}/aptarchive/ backports/main i386 Packages + *** 2.0~bpo1 0 + 100 ${tmppath}/rootdir/var/lib/dpkg/status + 1.0 0 + 500 file:${tmppath}/aptarchive/ stable/main i386 Packages" aptcache policy coolstuff + + + + +msgmsg "Check for package-specific never pin" +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: never +" > rootdir/etc/apt/preferences + +testfailureequal "Reading package lists... +E: ${tmppath}/rootdir/etc/apt/preferences: The special 'Pin-Priority: never' can only be used for 'Package: *' records" \ + aptget install -s coolstuff -o PinPriority=0 |