Reinstalling all your OpenBSD packages with pkg_add’s fuzzy matching feature

Last week, in classic Lawrence fashion, I somehow hosed my OpenBSD ports tree while doing some crazy experiments. It got to the point where make package would fail on certain ports like archivers/xz; if I tried it on those ports, I would get this funky error:

Error: /usr/ports/pobj/xz-5.0.4/fake-amd64/usr/local/share/locale/cs/LC_MESSAGES/ does not exist

Since MO files are related to GNU gettext, I tried to delete my gettext package along with all its dependencies and reinstalling them but it still produced the same error.

At that point, I decided to use a bigger hammer. The plan was to uninstall all packages and then reinstall them. That sounds tedious, but then I remembered reading that OpenBSD’s pkg_add tool has a “fuzzy adding” feature. I have never tried it before, but OpenBSD’s tools tend to Just WorkTM so I decided to give it a shot.

The two relevant pkg_add flags are -l and -z, and they are described on the pkg_add man page as follows:

-l file  Installs packages from the raw output of pkg_info(1), as saved
	 in file.  Generally, use with pkg_info -m >file, to reproduce an
	 installation from machine to machine.  With -z and -l pkg_add
	 will try its best to reproduce the installation, even if the
	 version numbers don't quite match and even if some packages
	 cannot be found.

-z	 Fuzzy package addition: pkg_add should do its best to match
	 package names passed on the command line, even if the versions
	 don't match and it will proceed even if some packages can't be

That was pretty self-explanatory. The pkg_info -m command that is mentioned in the text is used to show only packages that have been manually installed. For example, if you install git with pkg_add git and it pulls down rsync as a dependency, git is considered the manually installed package while rsync is the automatically installed package.

So, armed with that knowledge, I proceeded with saving a list of manually installed packages:

pkg_info -m >packages.txt

And then came the scary step of uninstalling ALL packages!

pkg_delete -X

Next, I reinstalled all my packages using pkg_add’s fuzzy adding feature:

export PKG_PATH=${my_favorite_mirror}
pkg_add -z -l packages.txt

And off it went! It worked just like the usual pkg_add -ui.

At the end of the entire process, all my original packages have been reinstalled. And make package on those problematic ports works again!

As mentioned in the man page excerpt above, this feature can be used to quickly install the same set of packages on similar systems. For example, if you always install a selected set of packages on a laptop, you can quickly install the same set of packages on another laptop with this technique.

It’s always fun to find useful time-saving features in the excellent OpenBSD pkg_* tools. Hope this will help someone out there!