Can I use flakes within a git repo without committing flake.nix?

To put that even more succinctly:

  • path:<path> ~= cp -r <path> /nix/store
  • git+file:<path> ~= git clone file:///<path> /nix/store

After that, the flake is evaluated in its new path in /nix/store. This is how it actually works today, in the future there will be some fancy mechanism to avoid doing this copy while pretending it has happened.

cp -r obviously copies everything, while git clone only copies files that have been git add-ed.

The path variant is generally git-unaware, so you can’t ask nix to use a specific commit or branch instead of what the repository is currently at, and you can’t ask it to exclude the .git directory.

You typically want to exclude the .git directory for caching (because otherwise any change will bust the cache), so nix defaults to the git protocol if at all possible. Same with other VC systems. The heuristic is deterministic, and very stable, so there’s not really a reason not to do this.

@NobbZ I didn’t uderstand anything new, the philosophical meaning of self-contained was evident without comparing to MRE, I would better see examples and links to the code

E.g. "we need to copy whole dir, bc IF we would not copy THEN … "

But thank you for trying, no insulting, I understand that you cannot see what is in my brain


Thx @TLATER Now I understand more

But, probably, you should change

git+file:<path> ~= git clone file:///<path> /nix/store

To

git+file:<path> ~= git clone file:///<path> /nix/git (because it’s probably behavior similar to builtins.fetchGit)

Question:

Why the full directory is copied to nix store ? cp -r <path> /nix/store

Why not? … not copy anything at all? I mean, nix build path:. will just read flake.nix and flake.lock and imported nix files (if they exist) to build required derivations.

Wer would not be able to ensure it exists at all, nor that path literals would point at the same location.

nix build (or any flake related thing in general) does not imply that the flake is actually local by any means.

Also, if we wouldn’t copy the flakes content to the store, then ./. would be some /home/srghma/… for you, /home/nmelzer/… for me, and /Users/foo/… for someone running on the mac.

Even worse, how would you resolve a ./. in a “remote” flake without copying first? Fully rely on a temporary folder created by mktemp -d with a random suffix?

All of these do not sound quite reproducible to me, as the state of the system influences what you get out of the build.

TLater was talking about “conceptually” which skips away a lot of the details… What actually happens for git+file is much more involved than a simple git clone (would take far too long for huge repos), instead in reality a git ls-files or so is ran in the repo and all files listed get copied over. But as said, TLater did simplify for getting concepts over, rather than implementations. They would be in the way here.

Because the lazytree hasn’t been merged yet, as it causes much more troubles than you might think it would.

See above.

2 Likes

@NobbZ

I think i now understood (more) the answer on "Why to copy whole repo? What else it needs except flake.nix and flake.lock? " (after reading edolstra post about flakes on tweag once again)

flake is simply a source tree (such as a Git repository) containing a file named flake.nix

Because flake is a repo by desing

Whatever is refered to by the flake. Which potentially is everything in its location. Even with lazytree, you will not be able to know in advance what exactly a derivation needs to be able to build. So when you hit a src = "${self}" or src = ./. you have to copy everything to satisfy the build.

1 Like

To clarify- under the new abstraction, this can be resolved by triggering after such dynamic paths are encountered, and won’t necessitate performing a full copy regardless of such encounters, right? I just want to make sure we aren’t losing the primary aspect of lazy trees I was looking forward to.

Otherwise, it could be worth looking into a “temporary” nix-store entry that read-only-links the original source until it is sure it was actually utilized.

Note that https://devenv.sh lifts the restriction for files needing to be tracked by git.

The downside is that if there are many/big files in the repo, loading the flake takes a lot longer.

One use case is reading .env files from Nix, but that file shouldn’t be committed to git, since it contains secrets.

1 Like

One thing I’m not entirely clear on after reading this thread:

Is there any downside in using path:. when your flake only contains devShells?

I have several projects at work that has nothing to do with Nix, but I like to use flakes to install development tools, and I don’t want to add that to Git.

1 Like

You give up on the evaluation cache. For just a handfull of devshells, that’s likely negligible.

So for the problem where you want to keep a flake.nix to provide a dev environment for a repo. Why not put that repo in a subdirectory and keep your flake.nix/flake.lock/.envrc in the directory above?

Like this:

embassy-rs-dev/  
   flake.nix      <-- my flake just for `nix develop`
   flake.lock
   .envrc
   embassy/    <-- repo I'm working on

Could also make embassy-rs-dev into a repo that has embassy as a submodule. Then the versions of the flake.nix and the embassy repo are linked.

Edit: It appears that it matters a lot whether embassy-rs-dev is a repo or not. If it is not a repo, I get

copying ~/bburdette/op-code/embassy-rs-dev

Every time I nix develop. If I specify nix develop path:., it still does the copy.

But if embassy-rs-dev is a repo, then nix-develop is instant.