Lix lockfiles differ Nix lockfiles #472
Labels
No labels
Area/build-packaging
Area/cli
Area/evaluator
Area/fetching
Area/flakes
Area/language
Area/profiles
Area/protocol
Area/releng
Area/remote-builds
Area/repl
Area/store
bug
crash 💥
Cross Compilation
devx
docs
Downstream Dependents
E/easy
E/hard
E/help wanted
E/reproducible
E/requires rearchitecture
imported
Needs Langver
OS/Linux
OS/macOS
performance
regression
release-blocker
RFD
stability
Status
blocked
Status
invalid
Status
postponed
Status
wontfix
testing
testing/flakey
ux
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lix-project/lix#472
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Describe the bug
Given the following flake (kept very short for simplicity):
and a
.envrc
withAlso, run
direnv allow
.When I run
nix flake show
, I'll get the following output now:The direnv error is expected, more interesting is that both direnv and
nix
invocations (using Lix) re-lock thevmtools
input.The cause for that is that Nix locks the URL to
https://git.pub.solar/pub-solar/infra-vintage?dir=vmtools
in flake.lock whereas Lix locks it tohttps://git.pub.solar/pub-solar/infra-vintage
(since?dir
is a flake-specific thing and has nothing to do with libfetchers).Also, there's a
dir
attribute already in the lockfile-entry which is what flakes actually use. The URL parameter serves no additional purpose.Potential fixes
Bump lockfile version
I think it's valid to change the semantics of
flake.lock
, it's versioned after all.The actual issue here is that direnv uses a wrong Nix. A bumped lockfile version would make that clear (also, we should provide a nix-direnv version that uses Lix unless that already happened).
Just bumping it from 7 to 8 is not an option though: as soon as Nix does that (and the change is a different one), it will be pretty chaotic.
Doing
"version": "lix-N"
won't work since Nix expects the version to be an integer.Another option might be to bump the lockfile version very very high.
Maintain compat with Nix lockfiles
We could accept
dir
in libfetchers again and make sure it's kept in the locked URL.Opinions @jade @pennae @qyriad
Tested with
nix (Lix, like Nix) 2.92.0-devpre20240813_b016eb0
for CLI andnix-direnv 3.0.5
using Nix 2.18.5.I think that we're stuck between a rock and a hard place by cppnix versioned interface semantics, yet again. And this interface is ridiculously fragile.
Either we implement newer versions of their semantics (e.g. nix profile manifest), not care and simply be incompatible, drag them forward to our own semantics by laboriously porting patches to cppnix (e.g. integer overflow) or freeze our interface in time at some convenient version (e.g. nix protocol).
Honestly, the file format compatibility between Lix and CppNix is going to probably be the first thing to cause divergence. Especially flake lock files, because we are unlikely to want to merge flake internals changes from them.
Taking a step back, actually the bug is that we are not just accepting the lock file without modifying it when it is semantically identical, right? And likewise they are doing the same on 2.18. Maybe we should stop doing that? It would at least stop this user facing behaviour surviving more than one cycle.
So there's one case I can think of where it makes a difference, but I'm not sure if it's that realistic: what if you have a git server that accepts query params in its clone URLs (
dir
to be precise).I think the correct way then is to provide a URL with all the query params, but rely on attributes for the rest instead of additional query params:
However, I'm not sure if there's a reasonable way to differentiate between URLs requiring
?dir=
for the clone and URLs having it for flake reasons without refetching the input based on what's in the lockfile which is probably not desirable.In the example above the
dir
attribute is what makes the difference. So this seems at least theoretically possible.If we consider this case negligible, then we can surely avoid refetches (having a hard time to estimate the amount of hackery for that though). I think this is the only semantic difference we currently have in flake.lock, correct?
Agreed.
May I ask if you or anyfew else has a better idea than just bumping the version to a very high number (or actually, a negative number should also work since CppNix only accepts ranges of lockfile versions)? The problem I see right now is that we want CppNix to error out reasonably if it encounters a Lix lockfile, however if
"version"
is not an integer, you just something get something like this:EDIT: hmm, perhaps the "
dir
is a query param" thing isn't that unrealistic since e.g. tarball fetchers are also affected, I think?I don't actually think that we want cppnix to error out when it gets a lix lock file. The thing about the lock format is it's intended to just get dumped into fetchTree, and if the generator was different sure maybe it can think the locked urls are wrong and want to redo them, but it should just dump it into fetchTree and work, in a reasonable world.
This is in a similar vein to npm lock files where different implementations will resolve them differently but when you have a lock file it's cross compatible.
However, is our fetchTree incompatible? I don't know.
Personally I do not consider it acceptable at all to break CppNix being able to read our lock files and vice versa, even as I would rather think about other things than cleaning up other people's flake tech debt.
The most responsible thing to do is to find all the broken shit in the URL currently and eliminate it and make a new, standard, lock file version that CppNix supports. Also ideally reduce the amount of shit in the lock file that's implementation details like the ones that led to this problem in the first place. And finally don't immediately start writing files in the new version and breaking older software.
Apologies for the delayed response!
I agree that yes, if there's nothing to fetch, this isn't supposed to happen.
But I think it may be the desired behavior in one case, the tarball fetcher: there, flake-specific query params and the URL to fetch are mixed together quite badly. As a result, there's no reasonable way to check if the
?dir=
part of the URL is there for flake reasons or because it's needed for the download. Hence, the current behavior would be correct in this one case I think.Does that make (more) sense? :)
Ugh. Yeah it's probably reasonable, though putting ?dir in there would just break your flake as well, if it was required for the URL. None of what was designed into there was a good idea to begin with and we are paying the price.
Agreed!
Only trying to make it a little less weird for everyone :)
Yes. But that's the case already since #174 with the suggested workaround to do
{ url = ...; type = "tarball"; }
instead of the URL syntax.I guess that's enough informatino to give it a try.
Might take me a bit, currently preparing for the last math exam on my schedule :)
We don't have to be. I wrote a document that proposes a strategy that is very nice: we don't have to break backwards compat, we improve versioning, we don't break CppNix, and we decouple ourselves from CppNix lockfile semantics: https://wiki.lix.systems/books/lix-contributors/page/flake-stabilisation-proposal