Update from Ports removes dependency data

Luke Dean LukeD at pobox.com
Tue Apr 4 23:36:25 UTC 2006



On Mon, 3 Apr 2006, wc_fbsd at xxiii.com wrote:

> I recently noticed if I update a package from ports, the package manager 
> looses the dependency data for the package.  eg:  updating old version of 
> gettext
>
> # pkg_info -R gett*
> Information for gettext-0.14.5_1:
> Required by:
> libgpg-error-1.1
> libgcrypt-1.2.2
> gnutls-1.2.9
> p5-gettext-1.03
> gmake-3.80_2
>
> [[[ update from ports - make ; make deinstall ; make reinstall ]]]
>
> # pkg_info -R gett*
> Information for gettext-0.14.5_2:
>
> Is my procedure incorrect, or is this normal behavior?
>
>  -Thanks,  Wayne

This is normal.  It's what makes upgrading those ports that are required 
by lots of other ports so difficult.
Dependency information is version-specific.

If you run "pkg_info -r libgpg-error-1.1" you'll find that it still 
depends on gettext-0.14.5_1 until you rebuild libgpg-error.

Last weekend I wrote some scripts to help me deal with stale dependencies 
like this.  My code is such an ugly perl hack that I'm ashamed to post it, 
and my algorithm isn't really airtight, but I'll give you the algorithm 
I'm using.  The script just uses pkg_info, pkg_version, and grep.

1) I build a dependency hash by parsing the output of "pkg_info -ra".  The 
keys to the hash are the names of the installed ports with the versions 
stripped off.  The right-hand-side of the hash are the lists 
of dependencies with the version numbers stripped off.

2) I build what I call a "full" dependency hash from the dependency hash I 
built in step 1.  I do this by recursively getting the dependencies for 
every dependency in the hash from step 1.  The result is a hash just like 
the one from step one, only with the list of dependencies expanded to show 
all of the dependencies' dependencies, etc. all the way down the the ports 
that don't require anything.
As I'm building this, I also count how many levels down I have to recurse 
to build each entry and remember this number for each port.  I call this 
number the "degree" for the port.  To avoid rebuilding the same ports over 
and over again, ports with high degrees should be built after ports with 
low degrees.

3) I get a list of everything I want to upgrade by parsing the output of 
"pkg_version -qL "="".  That shows me which of my installed ports are not 
the same version as the port in the ports tree.  Usually I'll want to 
upgrade those ports.

4) I add to that list all of the ports that have outdated dependencies.  I 
get that list by parsing "pkg_info -ra" for each port and checking 
"pkg_info -e " for each dependency to see if it exists.  If it doesn't 
exist, then I assume I need to upgrade the requiring port.  Many times the 
only thing I gain by doing this is an update to the dependency information 
in the ports database, but sometimes (like with the recent libiconv 
upgrade) it's truly necessary.  I don't know of any way to 
programmatically gauge the importance of an upgrade - all I can tell is 
whether the version of the port listed as a dependency still exists.

5) I take the list of ports that I built in step 3 and 4, look them up in 
the "degrees" hash I built at the end of step 2, sort the output by the 
degree I determined in step 2 and then print the list.

Then I use that list to tell me which ports that I should consider 
rebuilding and in what order.

I used this script to help me upgrade all the ports on a system that 
hadn't been upgraded in about six months.  It worked pretty well.  It's 
not always perfect, though.  Dependencies can change dramatically between 
versions sometimes, and sometimes a port will depend on a port that 
doesn't exist in the database (like "linux_base") but this approach is far 
far better than me trying to do a big upgrade of several ports by hand 
when I can't immediately see the dependencies.  It also gives me the 
freedom/power to choose to build the ports I want to build, and to build 
them with the options I want to use.


More information about the freebsd-questions mailing list