Can't get rid of home-manager package

Or at least I think that’s what’s going on :thinking:

So I’ve been trying to learn Nix and I have been trudging along with this PR that adds the extrafiles plugin to the beets package. Initially I disabled the Python unit tests for the plugin just to try to get the thing running at all. Eventually I got it into a working state. I added my branch of my nixpkgs fork as an overlay to my configuration.nix.

Then I enabled and configured beets via home-manager, which is installed as a NixOS module. After a nixos-rebuild switch beets was installed, the new plugin was enabled, and I imported an album and it successfully used the new plugin to move related files along with the music files. Clearly the PR works in general.

So now I know it works, but I wanted to see how the unit tests would fare. I commented out the overlay and the beets config in home-manager, made sure to delete the result folder in nixpkgs, again ran nixos-rebuild switch, ran nix-collect-garbage -d, rebooted, probably ran garbage collection a few more times, thinking this would purge beets entirely from my system. And indeed it was not on the path any longer. But when I ran nix-build -A beets in the nixpkgs folder it completed instantly with only a few lines of output and didn’t run the numerous unit tests again. I found out about the --check option, so ran nix-build -A beets --check. It ran all the unit tests again, yay! Except by default the new plugin is disabled so that only checked that the base beets package tests work, not any of the plugins.

I still can’t figure out how to customize the input arguments with nix-build, so I thought maybe locally in nixpkgs I can just flip enableExtraFiles ? false to enableExtraFiles ? true. Nope, now I get error: some outputs of '/nix/store/nd4l6wjdpkagv9v9gg5adx88253cxi54-beets-1.4.9.drv' are not valid, so checking is not possible.

At this point I go back to my original question, why was beets not “installed” but even after garbage collection running nix-build -A beets was basically instant? It makes it seem like it’s still around on my system/cached. And now I am just wanting to completely nuke any references to beets for now just to rule out any leftover weirdness. OK let’s look in the store:

❯ sudo find /nix/store -name '*beets*'
/nix/store/fpjicwvy03g6ypri5g22w10a8bpzhxyy-home-manager/home-manager/modules/programs/beets.nix
/nix/store/wpvhvkrvll46snnpfrxbp5265jnsw589-nixos-20.09pre236721.840c782d507/nixos/pkgs/tools/audio/beets

There you are! I try deleting it from the store, it tells me it’s still referred to. OK what’s the referrer?

❯ nix-store --query --referrers /nix/store/wpvhvkrvll46snnpfrxbp5265jnsw589-nixos-20.09pre236721.840c782d507/nixos/pkgs/tools/audio/beets
/nix/store/1l208k7d2n3cpca081h6j9z4habwnccf-env-manifest.nix
/nix/store/3wkljzkax8yk3hwsamd7a7kwvwnkvfka-user-environment

I check out the first path and it’s home-manager apparently. So is it normal for beets to still be in the store after removing from configuration.nix and running garbage collection? Or does that maybe have nothing to do with my problem? If that’s the case, how do I try running the unit tests for the new beets plugin locally from the nixpkgs folder (meaning my locally cloned fork of nixpkgs repo)?

1 Like

I haven’t verified what I say below, so these are just my best guesses.

I feel like this just means that the new beets was never built before so there’s nothing to check. Maybe just try building normally?

You should probably also remove beets from your home-manager config and home-manager switch (accompanied by deleting old generations, garbage collection etc., you know the drill).

When I do that it’s still basically instant.

I don’t have a separate home-manager config, I use it as a NixOS module. So I don’t even have home-manager available as a CLI tool.

What’s the output like?

After adding in programs.beets.enable = false (whereas before I had just removed all mention of beets), rebuilding, garbage collecting, then removing that line and doing the rebuild, garbage-collect, etc. it seems nix-build -A beets is finally working as expected and trying to run the tests for the new plugin.

I still can’t figure out how to set enableExtraFiles to true using nix-build, so I’d be curious to know if there’s a way to do that, but for now I seem to be at a point where I can try to see if the tests can be made to work.

So now I know it works, but I wanted to see how the unit tests would fare. I commented out the overlay and the beets config in home-manager, made sure to delete the result folder in nixpkgs, again ran nixos-rebuild switch , ran nix-collect-garbage -d , rebooted, probably ran garbage collection a few more times, thinking this would purge beets entirely from my system. And indeed it was not on the path any longer. But when I ran nix-build -A beets in the nixpkgs folder it completed instantly with only a few lines of output and didn’t run the numerous unit tests again. I found out about the --check option, so ran nix-build -A beets --check . It ran all the unit tests again, yay! Except by default the new plugin is disabled so that only checked that the base beets package tests work, not any of the plugins.

Nix works based on derivations, which are represented with .drv files in /nix/store. Derivations describe a recipe to build a store path, and that resulting store path contains a hash over all the derivations inputs. This means that unless you make any change to the derivation or its inputs (which would then also influence the build), the store path won’t change. And if the derivation doesn’t change, there’s no point to building it again if the store path already exists.

This is what happened here: Nix computed all inputs for -A beets, determined the store path for the result, checked whether it existed already, which it did, meaning it was built already and it could reuse the result. This means that if you expect something to be built, but it’s not (because it already exists), then you didn’t change any inputs, and nothing would really change even if you did rebuild it.

Due to this, there’s also no point to rebuilding, garbage collecting or reboot, because all of these things won’t change the derivation inputs, and building whatever you built previously, even if you deleted all of /nix/store would still give the same result.

So the question becomes: How do you change inputs to a derivation? And the answer to this is with the Nix language. In your case, the default enableExtraFiles is false, so you want to write some Nix expression that gives you a derivation produced when setting that to true. Since the beets package is declared with callPackage (as all packages are), you can override such an argument by using .override { enableExtraFiles = true; } on the beets attribute. You can do this using nix-build with

$ nix-build -E '(import ./. {}).beets.override { enableExtraFiles = true; }'

I still can’t figure out how to customize the input arguments with nix-build , so I thought maybe locally in nixpkgs I can just flip enableExtraFiles ? false to enableExtraFiles ? true . Nope, now I get error: some outputs of '/nix/store/nd4l6wjdpkagv9v9gg5adx88253cxi54-beets-1.4.9.drv' are not valid, so checking is not possible .

Changing the default would have worked too, since this changes the Nix expression for the default beets attribute, but you need to not pass --check, so it’s just nix-build -A beets. --check, much like rebuilding/GCing/rebooting, has no effect on the inputs, and as such has no use in fixing any problems with the build. --check is really there to check for build determinism.

3 Likes

Thank you, that’s exactly what I was looking for!