As I previously mentioned in the "Moving to Wayland" post, I recently moved to a
new computer. Moving can be very annoying if you use a heavily configured system
and don't have all the configurations easily available to just move over. Since
I do regular backups of my files, which include a dotfiles
folder with all
(or almost all) configuration files for the programs I use, I thought it would
be straightforward.
While moving though, I noticed I didn't have an easy way to see and install all the programs I use. At that point I started to wonder about using a distro like NixOS that uses a declarative package manager at its heart precisely to make it easy to reproduce a system. But I like Arch Linux a lot, and there honestly isn't a reason I can't have that feature with it.
Declarative package management
So the aim was to have declarative package management to make future moves easier. Also, since then the packages are listed in a file, by versioning it in my backups I also gain the ability to rewind to an old version for free (if I want to revert some mistake in the package list, for example).
But having a simple list of the installed packages isn't the greatest thing about declarative package management. The greatest benefit is that you can organize that list in a way that makes sense to you, by reordering and grouping the packages. And you can leave comments all over the file, which is particularly useful to register the reason each package is installed, so that in the future you can use that information to remove a package when no longer needed.
A quick search on the web for declarative package managers for Arch Linux revealed aconfmgr and decpac. The former is more complete, featuring built-in configuration management as well, but that's overkill for me and it's in bash, so it's a no-go. The latter is very simple, you basically just have a file with the commands to install the packages and the packages themselves in a syntax similar to JSON. And it's written in python.
decpac also allows you to install from the AUR by relying on the yay tool. The AUR packages are identified by a simple markup before the package name.
decpac is almost perfect, but I didn't like that it did the command configuration and package listing in the same file, which made it need a more complex syntax, that is similar to JSON but not quite.
That's why I decided to create my own, which I called, very creatively, pcmn.
pcmn
pcmn is really simple, with less than 200 lines of python code. It is heavily inspired by decpac with the main difference being the simpler syntax. And it is very simple indeed:
- one package per line (but lines with no packages are allowed as well of course)
- everything after a
#
is a comment - optionally the package's group can be written inside brackets before the
package name. When no group is specified the default is assumed, which
installs from the official repository. The only other group is
aur
, which informs the package should be installed from the AUR using yay.
There are only two commands:
generate
creates a new package list from the currently explicitly installed packages (that is, dependencies won't appear in the list, which is fine since pacman will resolve them).apply
applies the package list, that is, packages not listed will be uninstalled and packages in the list that aren't present will be installed.
A separate config file in JSON can be used to change the commands that are used
for both the default and the aur
group, to list, install and remove the
packages.
I've been using it for a few months now and I'm really happy with it. As I mentioned, the main difference from decpac is that I split the configuration and the package list and I think it makes a world of difference. The package list is really clean and easy to add to. Here's a sample of mine:
# # Utilities # # Backups borg borgmatic python-llfuse # Needed to mount an archive # Notifications libnotify mako # Keyboard (Custom) interception-caps2esc # Switch Caps with ESC [aur] interception-space2meta # Use Space as Meta
Every time I notice I need a new package for something I add it to the list,
together with a comment with the reason why, and run pcmn apply
so that it
gets installed. When I need to install a package temporarily just do something
quick or some test, I install it manually using pacman as usual, so that the
next time I run an apply
it automatically gets uninstalled.
If you found pcmn interesting, check out its repository for some
more information. It's also easily installable from the AUR, which means
that after you generate
the package list, [aur] pcmn-git
will appear in
its own package list. I find that funny for some reason 😝.
And that's why I like python so much. With less than 200 lines of code I wrote a program that solves a real problem I was having. And it was fun to write too!