Subject: Alternatives system for pkgsrc
To: None <tech-pkg@NetBSD.org>
From: Julio M. Merino Vidal <jmmv84@gmail.com>
List: tech-pkg
Date: 01/20/2005 12:55:31
Hi all,

I've been working on an alternatives system for pkgsrc, similar to that
found in Debian.  It is not ready yet, but before continuing its
development, I'd like to ask for comments here (mainly if you agree to
this proposal or not).  (Before thinking "ugh, linux stuff", keep
reading ;).

But what is an "alternatives system"?  It is a framework that allows
multiple packages providing similar functionality to be installed
concurrently (by removing files with common names), and then using a
utility to set up those common names with symlinks to the preferred
program.

An example: consider nvi and vim.  ATM you can install both on a system
without problems, because neither of them registers itself as 'vi'.
However, it may be convenient to have such link, specially if the base
system does not provide a 'vi' program (ok, this example is not very
fortunate, but you get the idea).

But which program should the link point to?  We can't make that
decision, because it will vary depending on the administrator
preferences.

So here is where alternatives come to play.  You have a common class,
'vi', and a set of providers for it, 'nvi' and 'vim'.  Then, after
installing the packages, you can run an utility to choose which
provider should be used for a given class.

This can be extrapolated to several other packages such as emacs 20/21,
the java virtual machines (thus deprecating java-wrapper), the
python packages (deprecating python), MTAs, printing servers...
You can imagine this as a more generic solution for something we are
already doing in pkgsrc.

How does it work?  I've added an mk/alternatives.mk file (automatically
sourced by bsd.pkg.mk), that does everything needed based on some
variables (mainly it adds some stuff to the INSTALL/DEINSTALL scripts).
An example from nvi:

ALTERNATIVE_CLASSES=    vi
ALTERNATIVE_NAME.vi=    nvi
ALTERNATIVE_FILES.vi=   ${PREFIX}/bin/vi ${PREFIX}/bin/nvi \
                        ${PREFIX}/man/man1/vi.1 ${PREFIX}/man/man1/nvi.1

Aside changes to the Makefiles, there is also a tool, named
pkg_alternatives.  It is used to manage the alternatives database at
(de)installation time and to change the defaults.  It is a short shell
script.

Whenever a package providing an alternative is installed, it gets
registered in the database.  If the class didn't exist before, it
becomes the default for such class.  Otherwise, the class is left
unmodified.  I.e., if you install nvi and then vim, vi would point
to nvi (by _default_).

When a package is removed, the alternatives system checks if it was
the current setting for a class; in such case, it tries to fall back
to another one in the same class.  If none is found, the class is
automatically removed.

The register and unregister actions described above are internal and
should not be manipulated by the end user.

However, there are also two "public" actions: change and status.
change is used to manually map an alternative to a class, while status
is used to check the current status of a class.

Let's see some examples:

[dawn pkgsrc] # pkg_alternatives status vi 
pkg_alternatives: `vi' is currently set to `nvi'
pkg_alternatives: available alternatives: nvi vim 
[dawn pkgsrc] # pkg_alternatives change vi vim
pkg_alternatives: changing class `vi' to alternative `vim'
pkg_alternatives: linking `/usr/pkg/bin/vi' to `/usr/pkg/bin/vim'
pkg_alternatives: linking `/usr/pkg/man/man1/vi.1' to
`/usr/pkg/man/man1/vim.1'

Note that each alternative is a group of files, thus you always get a
consistent setup for a given class.  This is specially useful when
considering 'jre' and 'jdk' as classes (instead of having classes for
each of the binaries, which I tried first but seems a PITA).

Also note that the links go this way: /usr/pkg/bin/vi -> sysconfdir/vi
-> /usr/pkg/bin/nvi.  sysconfdir is used here so that this can be
configured on a system basis if sharing /usr/pkg.  This is also how
the Debian's alternative system works.  I.e., the change action never
modifies anything under prefix.

I've modified nvi, vim, sun-jre15, sun-jdk15 and kaffe so far to test
this, and I think it's working quite well.  For the java packages,
some changes are required in the java-env.mk file to make things as
simple as possible.

Not attaching any patches because they are quite large but mostly
straightforward.

What do people think?  I would like to get this finished and committed
soon, if there are no big objections.

Thanks,

-- 
Julio M. Merino Vidal <jmmv84@gmail.com>
http://www.livejournal.com/users/jmmv/
The NetBSD Project - http://www.NetBSD.org/