There are two functions for fetching from a generic git repository, fetchgit
from nixpkgs
and fetchGit
which is a built-in function. What is their difference and is one to be preferred over the other?
builtins.fetchGit
was added in 2.0, and from the release notes:
builtins.fetchGit
allows Git repositories to be fetched at evaluation time. Thus it differs from thefetchgit
function in Nixpkgs, which fetches at build time and cannot be used to fetch Nix expressions during evaluation.
What’s the difference between build time and evaluation time in nix?
nix-instantiate
evaluates a Nix expression to produce a derivation. nix-store --realise
will then build a derivation and produce the outputs. nix-build
is essentially a wrapper around both.
You can also see this in nix repl
where running builtins.fetchGit
immediately fetches the repo and gives you info about it:
nix-repl> builtins.fetchGit { url = "https://github.com/NixOS/patchelf"; }
{ outPath = "/nix/store/hl1kqvll4km3p8ia9vlgggxjwvsyg6w1-source"; rev = "1bc54f0f74ae3a307aef68e2923661dbf4e1cd76"; revCount = 335; shortRev = "1bc54f0"; }
whereas fetchgit
evaluates to a derivation whose builder is a script that uses git
to check out the repo, so if you evaluate it in nix repl
all you get is a derivation, and you have to actually build it before you get the git repo.
I find it helpful to think of the nix client and nix daemon to be separate things.
-
The nix client is responsible for evaluating the nix expression language and produces build recipes (.drv files) and fixed-output files. The fixed-output files are when file paths are being used for example. Or any of the builtins.fetch* methods. It then talks to the nix daemon to add those to the store and build them.
-
The nix daemon is responsible for the whole
/nix
folder. It has a RPC protocol to receive fixed-output files and .drv files. It can be asked to build derivations… Some of those derivations have a determined fixed output and are also implemented as fetchers.
Even in single-user mode, the nix client and daemon are just in the same process.
I’m thinking that the difference between the fetchGits can be useful depending on whether you’re in a dev environment or staging environment.
Suppose you’re trying to setup CI/CD system using Nix for your organization. Then the CI runners need to use Nix to fetch private source dependencies from your Gitlab server. It one uses SSH keys to do this, then it might be nice to bake in SSH keys into the Nix runner image, but also prevent the user who submits the job from acquiring those keys. This means using instead pkgs.fetchgit
or pkgs.fetchgitPrivate
.
fetchgitPrivate has been removed in master, builtins.fetchGit as it is able to use native auth methods to pull down sources, thus making fetchgitPrivate obsolete.