`nix eval --raw nixos.PACKAGE.outPath` prints wrong path

nix eval --raw nixos.git.outPath (and sudo nix eval --raw nixos.git.outPath) prints a path which is a) completely wrong and b) doesn’t even exist:

$ nix eval --raw nixos.git.outPath; echo
/nix/store/cpx9hzqcxci468qjwx1yk9k8rwmhlqxl-git-2.31.1
$ sudo nix eval --raw nixos.git.outPath; echo
/nix/store/cpx9hzqcxci468qjwx1yk9k8rwmhlqxl-git-2.31.1
$ ls -l "$(nix eval --raw nixos.git.outPath)"
ls: cannot access '/nix/store/cpx9hzqcxci468qjwx1yk9k8rwmhlqxl-git-2.31.1': No such file or directory
$ ls -l "$(which git)"
lrwxrwxrwx 4 root root 62 Jan  1  1970 /run/current-system/sw/bin/git -> /nix/store/2hnhbics0f5vvxgw7xldjbi82bhgkjp4-git-2.31.1/bin/git

What gives?

The reason I’m querying this is that I want to source a file installed as part of Git in my .bashrc.

It is not completely broken, which is also a bit strange. nix eval --raw nixpkgs.bash-completion.outPath prints what looks like the right path.

nix eval --raw nixpkgs.gitAndTools.gitFull, seen here, prints a different non-existing path.

And finally, nix eval --raw nixos.gitFull, which uses the name of the package currently in environment.systemPackages (my bad), also prints a non-existing path.

When you use eval, it will only evaluate the Nix expression corresponding to the attribute. If you want the path to exist, you need to build the corresponding derivation (e.g. with nix build).

If the output path of a package does not match the one installed on your system, you are using a different channel.

I only have one channel, since I installed a couple days ago:

$ sudo nix-channel --list
nixos https://nixos.org/channels/nixos-21.05

I don’t understand what you mean by this. Which Nix expression could nix eval --raw nixos.gitFull be evaluating, if not the path to the currently installed “gitFull” package from the “nixos” channel?

Huh. A sudo nixos-rebuild switch later and the path is now correct. Not quite sure what happened there.

You probably did a nix-channel --update before (probably with sudo). This updated the channel (and thus the derivation for git) but did not rebuild the derivation. If there was an update for git, then it had a different store path before.

Your system does now know about the new version but has not installed it yet, just like an apt update without apt upgrade.

The nixos-rebuild switch built the derivation and thus installed the update for git in the new outPath.

The nixos in the package name is actually the channel name, so what you do with your command is not asking for the path where git is installed but for the path where the derivation output will be placed once it is built. You can do that for not installed packages, too.

If you want to get the path to where git is currently installed then you can use

dirname $(dirname $(readlink -f $(which git)))

but this might conflict with a user installed git package when you actually need the system installed gitFull package.

I’m not aware of another way of getting the installed path, maybe nix-store (or was it nix store?) might have something for that but I’m currently on my mobile phone and have no NixOS near me.

EDIT:
  • Add readlink -f to command for getting git store path
1 Like

You can also use

dirname $(dirname $(readlink -f /run/current-system/sw/bin/git))

to make sure that the system’s git is used. So when you install gitFull through /etc/nixos/config.nix, this will be used, even though you installed another version as user using e.g. nix-env -iA nixos.git.

1 Like