2026-06-06
#package_managers #archlinux #supac #programming | Status: Complete
A post briefly detailing how there is so much weird stuff going on in pacman (or any other AUR helper for that matter) and how I work around it to give a consistent interface in supac. Note that I am by no means an expert in how pacman should be structured. These are just my ramblings on the loose.
Pacman's behaviour and features (often the lack thereof), makes 0 sense to me.
You'd think that this is a straightforward query to ask a package manager. And I for one truly believe it is. I'd be lying if I say it isn't.
Well, you're out of luck. Pacman (or ALPM's database rather) contains no such metadata. In fact, there's no way to construct this either, without either:
pactree from
pacman-contribWhy do I need this in supac? The reason is straightforward. Let's say
you had the package quickshell explicitly listed in your
config, and then you delisted it (because fuck writing your own config,
just use ironbar ffs). So the straightforward method would be to use
paru --remove --nosave --recursive --unneeded quickshell,
but now this would give you a bunch of warnings and do nothing.
Why? Well, you liked skwd-wall, and used it for setting
your wallpaper. Tough luck. Well, quickshell is a
dependency, and is therefore, omitted out of the list. WITH NOTHING ELSE
BUT A WARNING.
To be fair, it is kind of obvious with how pacman works that it is
meant to be used in porcelain mode pretty much all the time, with the
exception of the --query flag options which offer some
plumbing modes. But seriously, at the very least, pacman
should offer two modes of operation, both porcelain and
plumbing.
--cascade?You do that right now, but one day, you'll end up removing
everything, including the fundamentals like curl and
flatpak.
The better behaviour is a rather trivial fix. If they're required by other packages, simply mark them to be installed as a dependency instead, ignore them with a warning, and remove whatever else it is that can be removed.
Instead, pacman just warns, and then does... nothing. It's still marked explicit.
At the time of writing, it doesn't. But the plan is straightforward,
although a bit of a hack. We take the list of packages not present in
the config from the explicit install list. Then, we mark them as
dependencies. All of them. The next step is straightforward. Just remove
the unneeded dependencies. But there's tiny bit of a semantics problem
here. It doesn't act as the clean command I envisioned. Instead, it acts
as a "mark dirty + cache trim" command (the second step is literally
what happens in the clean-cache subcommand in supac). Oh
well, I guess it works for now. Besides, the semantics of cache cleaning
for arch backend is wrong from the get-go, but more on that later.
Kind of relates to the above, and is basically a mirror of what
pacman doesn't do. Say you want dconf explicitly now, but
it's already installed as a dependency of nautilus.
However, there's a catch. You install it, but it's already installed. What do you think should happen? Well, pacman does a force reinstall. Not necessarily a bad thing, but really just better to have some flag around it instead.
It just reinstalls, and then does... nothing. The package is still
installed as a dependency, so if you happen to remove
nautilus later, dconf will be removed as a
transitive unused dependency.
Just... mark it explicitly installed. A very low cost operation. In fact, that's exactly what supac does. I genuinely do not understand why this is not the norm here.
As I mentioned above, the process of removal of packages leads to the removal of extra builddep sort of packages as well. Which isn't really a bad thing, but it messes the semantics of what clean and clean-cache are supposed to mean individually. If I was to do actual cache management, I'd have to... depend on paccache from the pacman-contrib package, or read all of pacman cache myself, while locking the database to prevent concurrent pacman modifications, and then do pruning and whatnot... which, now that I think of it, isn't all that impossible.
In fact, perhaps I can enable a stateful supac where the last epoch was the one that was stored, and anything before it will be removed. Although this only works for arch packages, and I'd really like for it to work for everything.
I truly think that this is what they're trying to follow with their
package management ecosystem. Which... would've been very nice if they
were actually thorough with it. One CLI to rule them all. Joking, but
one CLI to provide a plumbing CLI for ALPM's operations and querying
would've actually been really nice. Except, they didn't bother with that
and made a mash-up of different, unrelated functionalities together.
This was... unexpected, to say the least. The alternative would've been
to provide all of it in one single unified interface (not binary, but
interface) and then let us use that. However, everything's so badly
split out, with so much important and essential stuff left out in the
pacman-contrib package. And that's not there by default.
That kinda sucks.
You can argue that libalpm exists and that I shouldn't really be relying on the CLI behaviour anyways. So let me in on a bit of history about this project. I started out with pacdef, which is now defunct, and then metapac, which changed opinions from full scriptability to barely package management.
I was fully sold on the idea that there can be a scriptability and configurability layer to package management in Archlinux a la nixOS. I still believe I'm right, and that's why I chose a language which is a shell like language in nature. This allows for powerful scripting right at the config layer, and the difference between the (hopefully future) rebuild and update command would save an insane amount of time in the re-evaluation, which is where nix the package manager and nix the language toolchain both suck ass. And it has been a step in the right direction so far.
Anyways, back to the point, the reason I started supac was that I needed finer control over all the aspects of package management and features a la nix. But the reason metapac had to be forked from pacdef was because the latter was unmaintained and when alpm.rs bumped, builds and usage both started failing really badly. Anyhow, we settled on the design of having the package manager CLI being the interface because that is simply lesser maintenance effort. Although, I am reasonably certain, interfacing with ALPM probably won't solve my problems much efficiently either.
There might be a follow-up on how nix 'fixes' this (by probably ignoring most of the issues here). The reason I don't main nix, even though I've been dabbling in it lately, is simply because holy shit do derivations take a fuckton of time.
In any case, this post was sort of a mess. I had a lot of ideas running in my head and a lot of frustrations from considering edge cases again and again. It literally made me pause development work and write this piece for once. And clearly, my ramblings are... visible.