3

I use NixOS, Nix version 1.10. nix-env, Nix package manager's installation command, creates a new generation every time you install a package. This way different package configurations are stored in separate generations, and you can switch between them to rollback to previous states of the system, where you had different packages installed from now.

Suppose I installed package emacs, which created a new generation:

$ nix-env --list-generations
1   2015-09-18 14:32:51   
2   2015-09-19 15:41:58   (current)

Generation 1 doesn't contain emacs, generation 2 does. If I switch to generation 1 and delete generation 2, that means I lose emacs:

$ nix-env --switch-generation 1
switching from generation 2 to 1
$ nix-env --delete-generations 2
removing generation 2

The information from running --delete-generations operation is too scarce, and adding --verbose or --dry-run doesn't specify the list of packages removed. Even -vvvvv isn't helpful.

$ nix-env --dry-run --delete-generations 14
(dry run; not doing anything)
would remove generation 14
$ nix-env --verbose --dry-run --delete-generations 14
(dry run; not doing anything)
evaluating file ‘/nix/store/13lmbyk148z95sp96gh0vr2b867ypl8g-nix-1.10/share/nix/corepkgs/derivation.nix’
would remove generation 14

But how do I know that I lose emacs? Is there any command or very simple script to view a list of packages that I would lose if I permanently delete a generation? Or is there a way to view a diff between 2 generations? I strive for the simplest idiomatic solution.

2 Answers2

5

This depends on what you mean by "lose a package".

Assuming you mean:

won't be able to run the commands provided by the package after deleting the generation

If you delete a non-current profile all commands will still be there. The profile is self-contained.

To see what the current profile contains:

nix-store --query --references /nix/var/nix/profiles/per-user/$USER/profile

That is the user profile. To see the system profile:

nix-store --query --references /nix/var/nix/profiles/system

There might be a simpler way, but using the above we can find the answer:

# Replace $1 by previous profile number
nix-store --query --references /nix/var/nix/profiles/{system,per-user/$USER/profile} > /tmp/current-packages
nix-store --query --references /nix/var/nix/profiles/{system,per-user/$USER/profile-$1-link} > /tmp/prev-packages 
# The packages "lost" by changing profile from current to profile-$1-link is the set difference
comm -32 <(sort /tmp/current-packages) <(sort /tmp/prev-packages)

If you instead mean:

which packages will be "physically" deleted

I think it's a bit more tricky. A possible starting point is to use nix-store --query --roots on each package in the profile to be deleted.

1

Not exactly what you need, but if you know the generation number you can do a diff between two generations.

You can use nix-store -q --references to retrieve the list of derivation ('packages') a derivation depends on. And your 'system configuration' is just another derivation!

So essentially an example would be:

diff <(nix-store -q --references /nix/var/nix/profiles/system) <(nix-store -q --references /nix/var/nix/profiles/system-615-link)