Provide an alternatives system to allow users to select which package provides a file.
'/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.
An alternative would be specified in a PKGBUILD as:
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
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.
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?
On installation of a package with an alternative, the .ALTERNATIVE file is extracted to:
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
pacman -F... pacman -Ql <pkg>