Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 Oct 2000 23:59:47 -0800
From:      Tim Kientzle <kientzle@acm.org>
To:        "Daniel C. Sobral" <dcs@newsguy.com>
Cc:        Patrick Bihan-Faou <patrick@rageagainst.com>, libh@FreeBSD.ORG
Subject:   Making the Packages System Better
Message-ID:  <39FFCD73.7364C2BF@acm.org>
References:  <39DCC860.B04F7D50@acm.org> <20001006155542.A29218@cichlids.cichlids.com> <39F3CDD7.15B889E7@acm.org> <20001023190412.B507@cichlids.cichlids.com> <39F47E98.4BB647AA@acm.org> <20001023202244.B10374@cichlids.cichlids.com> <39F48F4A.38D458C2@acm.org> <39FCF244.5A8C8E59@newsguy.com> <39FDC12E.304B0011@acm.org> <39FE2406.150CA3B1@newsguy.com> <00cb01c042f1$1a347190$040aa8c0@local.mindstep.com> <39FE562C.714DBE7C@newsguy.com>

next in thread | previous in thread | raw e-mail | index | archive | help
"Daniel C. Sobral" wrote:
> Somehow I dislike PATHs, MANPATHs and LIBPATHs with 40 or 50 entries, I
> dislike a /usr that won't fit in one screen, I dislike having programs
> all over the place, I dislike having to edit /etc every time I want to
> make a new program available, and I specially dislike having to instruct
> users in setting up their accounts to be able to use a new program .

The following is an outline of an approach to package management
that addresses all of these concerns, does not require a package
database, and involves minimal automation.  Just to make things clear,
I'm specifically talking about pre-compiled packages such as would
be downloaded from the FreeBSD website or installed from a CD-ROM.

1) Each package resides in it's own private directory.
   E.g., "foo" version 3.4 resides in /usr/packages/foo-3.4/
   From here on, I'll refer to /usr/packages/foo-3.4/ as PREFIX.

2) Certain directories within PREFIX have special meaning.
      PREFIX/bin - user binaries
      PREFIX/lib - programming libraries
      PREFIX/man - man pages
      PREFIX/include - C/C++ include files
      PREFIX/rc.d - boot-time startup scripts
      <others may be required>

   Directories not on this list have no special meaning and
   can be used however the package wants to use them.

3) Special link directories are created for those recognized
directories:
     /usr/packages/bin contains symlinks to /usr/packages/*/bin/*
     /usr/packages/lib contains symlinks to /usr/packages/*/lib/*
     /usr/pacakges/man/... tree contains symlinks to corresponding files
              in /usr/packages/*/man/...
     /usr/packages/include contains symlinks to
/usr/packages/*/include/*
	... etc ...

   Only recognized directories have their contents symlinked.
   For example, PREFIX/private is never symlinked, nor is
   PREFIX/libexec or PREFIX/libdata or any other directory not on
   a particular list.  This is an important point.

Several important things to note here:

* User paths, MANPATH, LIBPATH, etc, do not ever need to be augmented
  when new directories are added, since those paths will all use the
  link directories.
* Package installation/deinstallation/upgrading are pretty
  trivial.  The only significant automation needed is to
  build/maintain the link dirs.
* Tentative upgrades are fairly simple: /usr/packages/foo-3.5/ can
  be installed without first removing /usr/packages/foo-3.4/
  (A little intelligence in building the link directories
  obviously helps here, but nothing unreasonable.)  In comparison,
  supporting tentative upgrades with the current approach requires
  the ability to archive all updated files individually and restore
  them for a rollback. (Question: do you correctly handle files
  that existed in the previous version but not the new version?)
* Rolling back an incomplete install is trivial: just delete the
directory.
  With the current system, rolling back an incomplete install
  requires that you make copies of any overwritten or altered files
  and keep track of each file that does get installed.  A crashed
  incomplete install is an ugly mess with the current defaults.
* No temporary directory is needed, since a new directory
  is created for each package.  If the package name isn't known in
  advance, you can create a temporary directory in /usr/packages
  and just rename it when the final name is known.  Similarly,
  package archive creation is much simplified (no need to fake
  a directory heirarchy).
* Some packages will obviously have to touch files outside of
  their directory; this could be handled in several ways, the easiest
  is to have an "install" script in the PREFIX dir and execute it
  after unpacking.
* Dependency handling is very efficient, even with networked installs.
  You can pull down a package and unpack it directly into it's PREFIX
  dir, then test dependencies and recursively install those
dependencies.
  By executing the "install" script and updating link directories as
  the recursion unwinds, you ensure that the visible parts of the
  installation are done in the correct order without requiring any
  temporary storage and without ever having to pause a download in
  progress.  In contrast, the current system requires you to either
  stop the current download to handle the dependency or have multiple
  pending installs sitting in temporary directories requiring additional
  disk space.  (This is admittedly a subtle point. ;-)
* The symlink directories should only contain symlinks and
  never contain actual files.  Otherwise, you run into some
  confusing maintenance issues.  (Learn from database design:
  don't mix derived data and primary data.)
* Packages should be compiled directly for their specific PREFIX.
  Files outside of the "special" directories do not get symlinked.
  Among other things, this avoids a lot of filename conflicts.
  (Two different spelling packages that have a "dictionary" file
  in PREFIX/private/dictionary won't conflict since that file
  doesn't need to be symlinked.)
  The basic principle: packages should keep their guts to themselves.
  In essence, the symlink directories are just how a package
  publicizes it's public interfaces.
* This does not require any changes to the existing "ports"
  collection as long as all ports are PREFIX-aware.  They
  can just be compiled with package-specific PREFIXes.
* The symlink dirs should probably build shadows of any
  directories.  E.g., /usr/packages/tcl-8.0/lib/tcl/xxxx
  should result in a real dir /usr/packages/lib/tcl/
  with symlinks to corresponding files.  That allows several
  tcl packages to have files within .../lib/tcl/
* Often, you need no special utilities at all with this scheme.
  For example, a list of installed packages:  ls /usr/packages

  
Building/maintaining the link directories is a pretty simple
exercise in walking a directory heirarchy that can be cribbed
from any number of sources.  As a crude first cut, you can simply:

cd /usr/packages/bin && ln -s ../*/bin/* .

But that rapidly runs into argument-length limits.  Besides,
it's much faster to compare the existing symlinks to the
desired symlinks and only alter the ones that have changed
(delete symlinks that point to deleted packages or add new
symlinks).  Updating all of the symlink directories shouldn't
take more than a second or two.  I have Perl code that does
most of this if you're interested (although it could be improved
by adding full shadow-dir support).

In short, I'd argue that this approach is significantly simpler
than the current package tools:  it doesn't require a database;
it makes it easy to provide such advanced features as
rollback, recovering failed installs and tentative upgrades.
I'm fairly confident that tools to support this approach would
be much simpler than overhauling the existing tools to provide
such features.  However, note that such tools would not work
with the current /usr/local tarpit, since they rely heavily on
the assumption that each package goes into its very own directory.
If you must support the /usr/local tarpit, then you've got some
ugly coding ahead.

Comments?

			- Tim Kientzle


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-libh" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?39FFCD73.7364C2BF>