User:Allan/Alternatives

From ArchWiki

The Idea

Provide an alternatives system to allow users to select which package provides a file.

Current Situation

'/usr/bin/sh' is a symlink to 'bash'. People may want to use a different shell interpreter for 'sh', e.g. 'dash', but this is currently not possible without rebuilding the bash package to remove the symlink first.

Proposal

makepkg

An alternative would be specified in a PKGBUILD as:

 alternative=('python')

Note that this is an array - a package could potentially provide more than one set of alternatives

Makepkg would add this information to the .PKGINFO file:

 alternative = python

The list of symlinks for an alternative is stored in a file called python.alternative and have format like:

 usr/bin/python -> python2
 usr/bin/idle -> idle2

This syntax assumes the symlinks will point to a file in the same directory. However full or relative paths can be specified if needed:

 usr/bin/java -> /usr/lib/jvm/java-7-openjdk/jre/bin/java
 usr/bin/java -> ../lib/jvm/java-7-openjdk/jre/bin/java

Directories can be symlinked just like files.

 usr/include/lua -> lua-5.2

Note the top entry is the primary alternative and will be used in some pacman output (the master alternative in Debian/Fedora speak). The rest are what is dragged in with it (slaves in Debian/Fedora speak...).

These files are stored in the package root with name

 .ALTERNATIVE.python

TODO

Should we have a way of globbing and what syntax? e.g.

 usr/include/* -> lua5.1/*

That would take all files in the package directory usr/include/lua5.1/ and symlink them into usr/include.

TODO

Should we have a way of piggybacking alternatives? E.g. python2-pip may way to piggyback on the python2 package's python alternative. No other implementation has this. Does this force packagers decisions onto the user, or should there be a way to avoid it?

pacman

Installation

On installation of a package with an alternative, the .ALTERNATIVE file is extracted to:

 /var/lib/pacman/local/python2-2.7.17-1/alternative.python

If the primary alternative symlink is not present, this package becomes the active owner of that alternative on this system. This is recorded with symlink is placed in:

 /var/lib/pacman/alternative/python/python2 -> /var/lib/pacman/local/python2-2.7.17-1/alternative.python

All symlinks specified in this file are created.

If the primary alternative symlink is present on the system, then nothing happens on package install.

TODO: Update handling. The symlink recording active alternatives will need adjusted with each update. Makes sense if we need to rescan the alternatives file and adjust.

TODO: Should we only check the primary alternative symlink? What is the behaviour when secondary symlinks are present in the system? Skip with a warning?

TODO: output - both when activating an alternative, and when not activating (like optdepends?)


New pacman option examples

List all alternatives from installed packages

 $ pacman -A
 python ->
    python3 3.7.2-3 [active]
    python2 2.7.17-1
 sh ->
    bash 5.0.002-1
    dash 0.5.10.2-1 [active]

List installed alternatives for a given command

 $ pacman -A sh
 bash 5.0.002-1
 dash 0.5.10.2-1 [active]

Update alternative (print error if mismatch between alternative name and package):

 $ pacman -Au sh bash
 usr/bin/sh -> bash

(only print the primary alternative?)

NEEDS WORK List all symlinks provided by an alternative:

 $ pacman -Ai python2
 python:
   usr/bin/python -> python2
   usr/bin/idle -> idle2
   ...


Other options requiring behaviour changes

pacman -Si <pkg> - prints alternatives like dependencies
pacman -Qi <pkg> - prints alternatives and also note whether alternative is active
pacman -Qo <alternative symlink> - assigned ownership to the package providing the alternative

Also?

pacman -F...
pacman -Ql <pkg>