]> git.saurik.com Git - apt.git/commitdiff
specific pins below 1000 cause downgrades
authorDavid Kalnischkies <kalnischkies@gmail.com>
Wed, 7 Aug 2013 16:00:07 +0000 (18:00 +0200)
committerMichael Vogt <mvo@debian.org>
Thu, 8 Aug 2013 13:16:18 +0000 (15:16 +0200)
We start your quest by using the version of a package applying to a
specific pin, but that version could very well be below the current
version, which causes APT to suggest a downgrade even if it is
advertised that it never does this below 1000.

Its of course questionable what use a specific pin on a package has
which has a newer version already installed, but reacting with the
suggestion of a downgrade is really not appropriated (even if its kinda
likely that this is actually the intend the user has – it could just as
well be an outdated pin) and as pinning is complicated enough we should
atleast do what is described in the manpage.

So we look out for the specific pin and if we haven't seen it at the
moment we see the installed version, we ignore the specific pin.

Closes: 543966
apt-pkg/policy.cc
test/integration/test-bug-543966-downgrade-below-1000-pin [new file with mode: 0755]

index 4ae3b5f8705bea5fa1f2cee782af327e16b9b106..0a06cc6e3d769f7b072f81144daff2d586dd96dc 100644 (file)
@@ -166,11 +166,15 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk
       tracks the default when the default is taken away, and a permanent
       pin that stays at that setting.
     */
+   bool PrefSeen = false;
    for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
    {
       /* Lets see if this version is the installed version */
       bool instVer = (Pkg.CurrentVer() == Ver);
 
+      if (Pref == Ver)
+        PrefSeen = true;
+
       for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF)
       {
         /* If this is the status file, and the current version is not the
@@ -187,26 +191,33 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk
         {
            Pref = Ver;
            Max = Prio;
+           PrefSeen = true;
         }
         if (Prio > MaxAlt)
         {
            PrefAlt = Ver;
            MaxAlt = Prio;
-        }       
-      }      
-      
+        }
+      }
+
       if (instVer == true && Max < 1000)
       {
+        /* Not having seen the Pref yet means we have a specific pin below 1000
+           on a version below the current installed one, so ignore the specific pin
+           as this would be a downgrade otherwise */
+        if (PrefSeen == false || Pref.end() == true)
+        {
+           Pref = Ver;
+           PrefSeen = true;
+        }
         /* Elevate our current selection (or the status file itself)
            to the Pseudo-status priority. */
-        if (Pref.end() == true)
-           Pref = Ver;
         Max = 1000;
-        
+
         // Fast path optimize.
         if (StatusOverride == false)
            break;
-      }            
+      }
    }
    // If we do not find our candidate, use the one with the highest pin.
    // This means that if there is a version available with pin > 0; there
diff --git a/test/integration/test-bug-543966-downgrade-below-1000-pin b/test/integration/test-bug-543966-downgrade-below-1000-pin
new file mode 100755 (executable)
index 0000000..f602bea
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'i386'
+
+insertpackage 'unstable' 'base-files' 'all' '5.0.0'
+insertinstalledpackage 'base-files' 'all' '5.0.0-1'
+
+setupaptarchive
+
+STATUS=$(readlink -f rootdir/var/lib/dpkg/status)
+APTARCHIVE="$(readlink -f aptarchive)/"
+
+testequal "base-files:
+  Installed: 5.0.0-1
+  Candidate: 5.0.0-1
+  Version table:
+ *** 5.0.0-1 0
+        100 $STATUS
+     5.0.0 0
+        500 file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=0
+
+echo 'Package: base-files
+Pin: release a=unstable
+Pin-Priority: 99' > rootdir/etc/apt/preferences
+
+testequal "base-files:
+  Installed: 5.0.0-1
+  Candidate: 5.0.0-1
+  Package pin: 5.0.0
+  Version table:
+ *** 5.0.0-1 99
+        100 $STATUS
+     5.0.0 99
+        500 file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=99
+
+echo 'Package: base-files
+Pin: release a=unstable
+Pin-Priority: 100' > rootdir/etc/apt/preferences
+
+testequal "base-files:
+  Installed: 5.0.0-1
+  Candidate: 5.0.0-1
+  Package pin: 5.0.0
+  Version table:
+ *** 5.0.0-1 100
+        100 $STATUS
+     5.0.0 100
+        500 file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=100
+
+echo 'Package: base-files
+Pin: release a=unstable
+Pin-Priority: 999' > rootdir/etc/apt/preferences
+
+testequal "base-files:
+  Installed: 5.0.0-1
+  Candidate: 5.0.0-1
+  Package pin: 5.0.0
+  Version table:
+ *** 5.0.0-1 999
+        100 $STATUS
+     5.0.0 999
+        500 file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=999
+
+echo 'Package: base-files
+Pin: release a=unstable
+Pin-Priority: 1000' > rootdir/etc/apt/preferences
+
+testequal "base-files:
+  Installed: 5.0.0-1
+  Candidate: 5.0.0
+  Package pin: 5.0.0
+  Version table:
+ *** 5.0.0-1 1000
+        100 $STATUS
+     5.0.0 1000
+        500 file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=1000