[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

/etc/apt/preferences with pins for more than 2 sources



A few months ago I posted here, and on my web page, an /etc/apt/preferences
file which worked when using more than 1 non-Debian source, along with an
explanation of the problems involved.  I recently tried to use it on a
system with stable, testing, and unstable in sources.list and found that I
hadn't well accounted for such a setup.

I've re-worked the thing in light of that.  It's living at
http://www.argon.org/~roderick/apt-pinning.html, and here's a "w3m
-dump" version.  I'd greatly appreciate comments and criticisms.

--------------------------------------------------------------------------

Using APT with more than 2 sources
----------------------------------

APT's Default-Release setting (aka apt-get --target-release) is useful if
your /etc/apt/sources.list file contains exactly 2 releases (such as stable
and testing, or testing and unstable).  If you want to track more than 2
releases (stable, testing, and unstable, or two of those plus a non-Debian
source), it has problems.  This document explains how to do better.  Updates
can be found at http://www.argon.org/~roderick/apt-pinning.html.

Improved /etc/apt/preferences File
----------------------------------

First, here are some reasonable /etc/apt/preferences files for the common
cases.  The rest of this document describes what these are doing.

  * Track stable:

    Explanation: see http://www.argon.org/~roderick/apt-pinning.html
    Package: *
    Pin: release o=Debian,a=stable
    Pin-Priority: 900

    Package: *
    Pin: release o=Debian,a=testing
    Pin-Priority: 400

    Package: *
    Pin: release o=Debian,a=unstable
    Pin-Priority: 300

    Package: *
    Pin: release o=Debian
    Pin-Priority: -1

  * Track testing:

    Explanation: see http://www.argon.org/~roderick/apt-pinning.html
    Package: *
    Pin: release o=Debian,a=testing
    Pin-Priority: 900

    Package: *
    Pin: release o=Debian,a=unstable
    Pin-Priority: 300

    Package: *
    Pin: release o=Debian
    Pin-Priority: -1

"apt-get --default-release" Has No Memory
-----------------------------------------

When you run "apt-get -t unstable install foo", this sets
APT::Default-Release for this invocation of apt-get, but it doesn't
affect future runs.  This is useful in some circumstances, but
problematic in others.

The Good
--------

Say you've got testing and unstable in your sources.list, an APT::
Default-Release of "testing" in apt.conf, and a package foo which is
available from the releases like this:

    +------------------------------------------+
    |        |       |        priority         |
    |release |version|-------------------------|
    |        |       |no -t switch|-t unstable||
    |--------+-------+------------+-----------+|
    |testing |    1.1|         990|        500||
    |--------+-------+------------+-----------+|
    |unstable|    1.2|         500|        990||
    +------------------------------------------+

If foo isn't installed and you run "apt-get install foo" you get version
1.1 from testing, since that version has the highest priority.

If you run "apt-get -t unstable install foo" instead you get version 1.2
from unstable, since the -t switch temporarily causes that version to
have the highest priority.

foo will temporarily track unstable.  If version 1.3 is uploaded to
unstable while 1.1 is still in testing, we have:

    +---------------------------+
    | release  |version|priority|
    |----------+-------+--------|
    |installed |    1.2|     100|
    |----------+-------+--------|
    |testing   |    1.1|     990|
    |----------+-------+--------|
    |unstable  |    1.3|     500|
    +---------------------------+

The highest priority version is 1.1, but this is lower than the installed
1.2.  Since the priority of 1.1 is 990 (which is lower than 1000), apt-get
will not downgrade to it.  The next highest priority is 1.3 at 500.  Since
this is greater than the installed 1.1, it is selected.

foo will stop tracking unstable as soon as testing gets a version which is
as new as the version which is currently installed.  Say that version 1.3
migrates from unstable to testing, and then 1.4 is uploaded to unstable:

    +---------------------------+
    | release  |version|priority|
    |----------+-------+--------|
    |installed |    1.3|     100|
    |----------+-------+--------|
    |testing   |    1.3|     990|
    |----------+-------+--------|
    |unstable  |    1.4|     500|
    +---------------------------+

Since the unstable 1.4 version now has a lower priority than the installed
version, foo is not upgraded to it.  Often this is what you want.

The Bad
-------

APT::Default-Release's behavior works well when you're only tracking
two different releases, but with 3 or more it starts to go wrong.  When
you install a package from 1 of the non-default releases, it can be
immediately replaced with a newer version from another of them.

Consider:

    +-----------------------------------------------------------------+
    |        |       |                    priority                    |
    |release |version|------------------------------------------------|
    |        |       |APT::Default-Release|above /etc/apt/preferences||
    |--------+-------+--------------------+--------------------------+|
    |stable  |    1.0|                 990|                       900||
    |--------+-------+--------------------+--------------------------+|
    |testing |    1.1|                 500|                       400||
    |--------+-------+--------------------+--------------------------+|
    |unstable|    1.2|                 500|                       300||
    +-----------------------------------------------------------------+

With an APT::Default-Release of "stable" and no /etc/apt/preferences, if
you install the package with "apt-get -t testing install foo" you'll get
version 1.1 from testing.

The big problem happens when you run "apt-get upgrade": Version 1.2
from unstable has the same priority as the 1.1 just installed, so 1.1
(testing) is replaced with 1.2 (unstable)!

I fix this problem by giving testing and unstable different priorities.
With the explicit PINs from the above /etc/apt/preferences, version 1.2
from unstable has priority 300 compared to testing's 400, so the version
from testing remains installed.

The pin of other Debian releases at priority -1 is only a bit of
defensiveness.  This doesn't affect any Debian sources that I know
of (since they're all stable, testing, or unstable), so if a new
Debian source is added I'll have to decide what priority to give it.
Without this pin it'd come in at the default priority of 500.

Using Non-Debian Sources
------------------------

If you're using non-Debian sources, you've got the same problem, only
more so because there's no natural ordering as there is with Debian's
stable -> testing -> unstable.  Without explicitly listing them in
/etc/apt/preferences, they're all at priority 500, so a package
installed from one source can be replaced by a higher version supplied
by a different source.

A partial fix for this is to pin each source at a different priority.
Eg,

    Package: *
    Pin: origin marillat.free.fr
    Pin-Priority: 600

    Package: *
    Pin: origin www.ibiblio.org
    Pin-Priority: 610

    Package: *
    Pin: origin www.argon.org
    Pin-Priority: 620

These settings would mean that a package installed from www.argon.org
wouldn't automatically be replaced with one from the other two, and one
from www.ibiblio.org wouldn't be replaced with one from ma
marillat.free.fr.

Working in the other direction the packages would still be replaced,
however: If you've installed a package from www.ibiblio.org and a newer
version becomes available from www.argon.org, apt-get will upgrade to
it.  The only way I know of to prevent that is to explicitly pin the
package to the source via /etc/apt/ preferences.

--------------------------------------------------------------------------

-- 
Roderick Schertler
roderick@argon.org



Reply to: