-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restore input substitution #11701
Restore input substitution #11701
Conversation
The ability to substitute inputs was removed in NixOS#10612 because it was broken: with user-specified inputs containing a `narHash` attribute, substitution resulted in an input that lacked the attributes returned by the real fetcher (such as `lastModified`). To fix this, we introduce a new input attribute `final`. If `final = true`, fetching the input cannot add or change any attributes. We only attempt to substitute inputs that have `final = true`. This is implied by lock file entries; we only write a lock file if all its entries are "final". The user can specified `final = true` in `fetchTree`, in which case it is their responsibility to ensure that all attributes returned by the fetcher are included in the `fetchTree` call. For example, nix eval --impure --expr 'builtins.fetchTree { type = "github"; owner = "NixOS"; repo = "patchelf"; final = true; narHash = "sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM="; }' succeeds in a store path with the specified NAR hash exists or is substitutable, but fails with error: fetching final input '{"final":true,"narHash":"sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM=","owner":"NixOS","repo":"patchelf","type":"github"}' resulted in different input '{"final":true,"lastModified":1718457448,"narHash":"sha256-FSoxTcRZMGHNJh8dNtKOkcUtjhmhU6yQXcZZfUPLhQM=","owner":"NixOS","repo":"patchelf","rev":"a0f54334df36770b335c051e540ba40afcbf8378","type":"github"}'
Co-authored-by: Cole Helbling <[email protected]>
We haven't added the narHash attribute yet at that point. And if the caller uses getAccesor() instead of fetchToStore() (e.g. in `nix registry pin`), the narHash attribute will never be added. This could lead to a mismatch.
…astModified Fixes flake-regressions/tests/DeterminateSystems/fh/0.1.10: error: fetching final input '{"final":true,"narHash":"sha256-0dZpggYjjmWEk+rGixiBHOHuQfLzEzNfrtjSig04s6Q=","rev":"9ccae1754eec0341b640d5705302ac0923d22875","revCount":1618,"type":"tarball","url":"https://api.flakehub.com/f/pinned/nix-community/fenix/0.1.1618%2Brev-9ccae1754eec0341b640d5705302ac0923d22875/018aea4c-03c9-7734-95d5-b84cc8881e3d/source.tar.gz"}' resulted in different input '{"final":true,"lastModified":1696141234,"narHash":"sha256-0dZpggYjjmWEk+rGixiBHOHuQfLzEzNfrtjSig04s6Q=","rev":"9ccae1754eec0341b640d5705302ac0923d22875","revCount":1618,"type":"tarball","url":"https://api.flakehub.com/f/pinned/nix-community/fenix/0.1.1618%2Brev-9ccae1754eec0341b640d5705302ac0923d22875/018aea4c-03c9-7734-95d5-b84cc8881e3d/source.tar.gz"}'
Fixes flake-regressions/tests/DeterminateSystems/eva/0.1.0: error: 'lastModified' attribute mismatch in input 'https://api.flakehub.com/f/pinned/ipetkov/crane/0.14.1/018ac45c-ff5e-7076-b956-d478a0336516/source.tar.gz?narHash=sha256-mnE14re43v3/Jc50Jv0BKPMtEk7FEtDSligP6B5HwlI%3D', expected 1695511445
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're onto something, but I'm not completely certain that this solves the whole problem, and a partial solution will lead to complexity we'll have to maintain indefinitely. Let me explain.
A related problem that's not solved by this feature is the forward compatibility to add new metadata attributes (like lastModified
but new) to an input type.
A possible solution to that is to have an attributes = ["lastModified" "fancyNewAttr"];
argument, and then only return the requested attributes.
The default attributes
(when unset) could then be compatible with the current behavior.
This way, we only return attributes that are expected by the caller, and final
, as used in fetching/substitution becomes a derived property: whether all requested attributes are already specified in the input attrset.
(This PR also needs docs and tests, and while particularly the prior could be a useful way to think about the design, these are of secondary concern to the design question)
That's not a big problem: the fetcher can simply not return the new attribute if the input is marked as final. In fact, this PR does just that in the tarball fetcher. |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2024-10-23-nix-team-meeting-minutes-189/54841/1 |
This fixes the error '{"__final":true,"lastModified":1686592866,"narHash":"sha256-riGg89eWhXJcPNrQGcSwTEEm7CGxWC06oSX44hajeMw","owner":"nixos","repo":"nixpkgs","rev":"0eeebd64de89e4163f4d3cf34ffe925a5cf67a05","type":"github"}' resulted in different input '{"__final":true,"lastModified":1686592866,"narHash":"sha256-riGg89eWhXJcPNrQGcSwTEEm7CGxWC06oSX44hajeMw=","owner":"nixos","repo":"nixpkgs","rev":"0eeebd64de89e4163f4d3cf34ffe925a5cf67a05","type":"github"}' in flake-regressions/tests/nix-community/patsh/0.2.1 (note the lack of a trailing '=' in the NAR hash in the lock file).
Belated team discussion notes from 2 weeks ago:
|
We now just check that the fetcher doesn't change any attributes in the input, and return all the original attributes (i.e. discarding any new attributes and keeping any attributes that the fetcher didn't keep).
Simplified the semantics of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making final
a non-Input
argument may be a lot cleaner.
Otherwise, some comments.
This passed the full flake regressions test suite. |
It's now only allowed in fetchFinalTree, which is not exposed to users but only to call-flake.nix.
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2024-11-06-nix-team-meeting-minutes-192/55847/1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more suggestion, but let's move forward.
static RegisterPrimOp primop_fetchFinalTree({ | ||
.name = "fetchFinalTree", | ||
.args = {"input"}, | ||
.fun = prim_fetchFinalTree, | ||
.internal = true, | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static RegisterPrimOp primop_fetchFinalTree({ | |
.name = "fetchFinalTree", | |
.args = {"input"}, | |
.fun = prim_fetchFinalTree, | |
.internal = true, | |
}); |
Couldn't we construct the primop on the fly when loading call-flake.nix
?
That way we don't need internal
and internalPrimOps
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seemed tricky since this happens in libfetcher
rather than libexpr
, so it's not clear how to construct a singleton value. Or we could allocate a new PrimOp every time, but that would leak.
Motivation
The ability to substitute inputs was removed in #10612 because it was broken: with user-specified inputs containing a
narHash
attribute, substitution resulted in an input that lacked the attributes returned by the real fetcher (such aslastModified
). This could result in a different evaluation result, depending on whether the input was substitutable.To fix this, we introduce a new input attribute
__final
. This is for internal use only (specifically, bycall-flake.nix
) and may be removed in the future. If__final = true
, fetching the input cannot change any attributes and we ignore any new attributes returned by the fetcher. For example:Note the absence of the
lastModified
attribute usually returned by thegithub
fetcher.We only attempt to substitute inputs that have
__final = true
. This is implied by lock file entries; we only write a lock file if all its entries are "final".Context
Priorities and Process
Add 👍 to pull requests you find important.
The Nix maintainer team uses a GitHub project board to schedule and track reviews.