User:Allan/Alternatives
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>