NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.76k stars 1.52k forks source link

nix flakes: add support for git submodules #4423

Closed DanilaFe closed 3 years ago

DanilaFe commented 3 years ago

I recently learned about Nix Flakes, and I tried out making my blog a perfectly reproducible build. The trouble is, my blog uses a Git submodule to reference some code that I then present in my blog posts. This is fine and all, but I run into an issue - although I can fetch my blog source using Flakes' input attribute, it doesn't fetch submodules! This means that the code that I reference in my build process is simply not there.

This seems to be almost possible; from a brief glance around Nix's source code, I discovered that a flake input gets turned into a "regular" input, which can point to a git repo and have a submodules attribute that, I think, would do what I want. It feels as though it was intended that this would work, but it doesn't.

It doesn't work because, for a reason unknown to me, a flake input's attributes must all be strings (except for flake). Here's the code that rejects non-string arguments:

https://github.com/NixOS/nix/blob/724b7f4fb660212a97ba6482208c299158720c5b/src/libexpr/flake/flake.cc#L123-L127

If non-string arguments were not rejected, a submodules field could be forwarded to the Git input scheme, which I suspect would make this work. Is there a reason that Flakes rejects all non-string "third party" attributes? It puts them into an attribute set anyway. Right now, I'm falling into a rather amusing loop:

duality of nix

If submodules is a string, it's rejected by the Git input scheme. But if it's a bool, it's rejected by the Flake code.

hraban commented 7 months ago

In case anyone is interested in using submodules on flake inputs , not just the flake directory itself, you have to specifically use =1, not =true, and you have to use a "git" type input, notably not github:user/repo syntax because that's just a HTTP download of an archive from github's "download as .tar.gz" endpoint.

Example:

  inputs = {
    nyxt = {
      flake = false;
      url = "git+https://github.com/atlas-engineer/nyxt?submodules=1";
    };

C.f.

https://github.com/NixOS/nix/blob/31ffd0c1fe1d5112746f3c8d608cbfb4d6290d1b/src/libfetchers/git.cc#L270-L271

Update: Be careful, fetching from a git with submodules is not deterministic and you will get narhash clashes. See https://github.com/NixOS/nixpkgs/issues/100498 for workarounds using e.g. pkgs.fetchgit.

nixos-discourse commented 6 months ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/handling-git-submodules-in-flakes-from-nix-2-18-to-2-22-nar-hash-mismatch-issues/45118/1