pkg_add does not backtrack, does it?

Mike Meyer mwm-keyword-freebsdhackers2.e313df at
Fri Feb 9 00:27:38 UTC 2007

In <8b4c81f0702081553j7168846aj13c5b191d4bfb408 at>, Henry Lenzi <henry.lenzi at> typed:
> On 2/6/07, Mike Meyer <mwm at> wrote:
> > In <8b4c81f0702061514r5a753e48yea0ce9b937236fc3 at>, Henry Lenzi <henry.lenzi at> typed:
> > >  I haven't found the pkg_add code (it's in Ruby, is it?).
> >
> > It's in /usr/src/usr.sbin/pkg_install/add. And no, it's not in ruby.
> >
> > > But from the behaviour of pkg_add -r, it's safe to say that it
> > > doesn't backtrack to resolve dependencies, does it?
> >
> > Why should using a remote repository change the behavior of pkg_add?
> >
> > Are you sure you're not thinking of portupgrade? The -r otion to it
> > causes things to be recursive, and it is sourced in ruby. And it's in
> > the ports tree, not the base system (because it's sourced in ruby), so
> > you'll need to look for the source (or maybe a tarball) there.
> >
> > >  Like, for instance (a real example), during gnome2 installation on 6.2:
> > >
> > > warning: 'gstreamer-plugins-gconf-0.10.4_3,2' requires
> > > 'gstreamer-plugins-0.10.10,2', but 'gstreamer-plugins-0.10.9,1' is
> > > installed
> > >
> What I was saying is that, one way to go about it manually is hit
> Ctl-C, uninstall version 0.10.9,1, then proceed - because the update
> required package will be fetched (0.10.10,2). I was commenting the
> pkg_add did not do that - detect an outdated version and act upon that
> knowledge. i.e., removing it and installing the new one. Otherwise you
> would end up having wrong dependencies. This, of course, with pkg_add
> for stufflike Gnome, or KDE.

Um, if you stopped, uninstalled 0.10.9,1 and then installed 0.10.10,2,
then everything that required 0.10.9,1 winds up with a broken
dependency. Depending on the nature of the dependency, uninstalling
0.10.9,1 may well cause those applications - and not just their
dependency information - to be broken.

What pkg_add does doesn't break the dependency graph - you just wind
up with two versions of the package installed, one of which may be
broken. More importantly, it cuts down on the number of cases where
applications break, because the cases where replacing a port with a
newer version breaks a dependent port is usually where a file in the
old version doesn't exist in the new version - typically a shared
library that's changed version numbers. Installing them both means
both files are there, so the things keep working. Doing this "right"
requires that you uninstall any ports that depend on the old port,
then uninstall the old port, install the new port, then reinstall all
of it's dependencies.

When I think of classic AI backtracking strategies, they always search
*trees*. The dependency relationship is a DAG (at least, I hope there
are no cycles!). That makes things noticably harder. In particular,
since you need to go both up and down the tree, so you *can* encounter
cycles, which isn't true with a tree.

> Portupgrade, AFAIK, does upgrade fetching source, right? It's not the
> same thing.

Portupgrade can install from sources, from binaries using sources if
the binary isn't available, or only using binaries. It also will move
shared libraries in ports it's removing to a compatability directory,
so that ports dependent on them won't break.

Using "portupgrade -aR" will reinstall all installed packages that are
out of date, and all packages that depend on them. Adding a "P" will
make it try to install binary packages; adding "PP" will cause it to
only use binary packages.

As others have noted, you need an up-to-date copy of the ports tree
and INDEX for portupgrade. To do what it does, portupgrade needs both
the dependency information for the installed packages (this is, in
theory, available in /var/db, but the available tools make it trivial
to break that database) *and* the dependency information for all the
packages you're going to be installing. That's in the ports tree and
INDEX files.

If you were installing only binary packages, you could in theory build
the later by fetching each package in turn and extracting it's
dependency information. You would need to do this *before* you
installed any new packages, because the order that you install them in
is important.

As a final aside, I once discussed this with Jordan, and he claimed
that his decision to have pkg_add do both installation and dependency
checking was a mistake. It would better to have one tool for
manipulating packages - extract dependency information, install,
deinstall, etc.  - and one tool that dealt with the tree.

Mike Meyer <mwm at>
Independent Network/Unix/Perforce consultant, email for more information.

More information about the freebsd-hackers mailing list