1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-24 22:11:15 +02:00

Merge pull request #13159 from NixOS/ignore-dir

Avoid unnecessarily updating old lock files with 'dir' parameters
This commit is contained in:
Jörg Thalheim 2025-05-12 22:34:50 +02:00 committed by GitHub
commit 6fdb170fb3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 117 additions and 1 deletions

View file

@ -595,7 +595,7 @@ LockedFlake lockFlake(
oldLock = *oldLock3;
if (oldLock
&& oldLock->originalRef == *input.ref
&& oldLock->originalRef.canonicalize() == input.ref->canonicalize()
&& oldLock->parentInputAttrPath == overridenParentPath
&& !hasCliOverride)
{

View file

@ -289,6 +289,55 @@ std::pair<ref<SourceAccessor>, FlakeRef> FlakeRef::lazyFetch(ref<Store> store) c
return {accessor, FlakeRef(std::move(lockedInput), subdir)};
}
FlakeRef FlakeRef::canonicalize() const
{
auto flakeRef(*this);
/* Backward compatibility hack: In old versions of Nix, if you had
a flake input like
inputs.foo.url = "git+https://foo/bar?dir=subdir";
it would result in a lock file entry like
"original": {
"dir": "subdir",
"type": "git",
"url": "https://foo/bar?dir=subdir"
}
New versions of Nix remove `?dir=subdir` from the `url` field,
since the subdirectory is intended for `FlakeRef`, not the
fetcher (and specifically the remote server), that is, the
flakeref is parsed into
"original": {
"dir": "subdir",
"type": "git",
"url": "https://foo/bar"
}
However, this causes new versions of Nix to consider the lock
file entry to be stale since the `original` ref no longer
matches exactly.
For this reason, we canonicalise the `original` ref by
filtering the `dir` query parameter from the URL. */
if (auto url = fetchers::maybeGetStrAttr(flakeRef.input.attrs, "url")) {
try {
auto parsed = parseURL(*url);
if (auto dir2 = get(parsed.query, "dir")) {
if (flakeRef.subdir != "" && flakeRef.subdir == *dir2)
parsed.query.erase("dir");
}
flakeRef.input.attrs.insert_or_assign("url", parsed.to_string());
} catch (BadURL &) {
}
}
return flakeRef;
}
std::tuple<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragmentAndExtendedOutputsSpec(
const fetchers::Settings & fetchSettings,
const std::string & url,

View file

@ -72,6 +72,12 @@ struct FlakeRef
const fetchers::Attrs & attrs);
std::pair<ref<SourceAccessor>, FlakeRef> lazyFetch(ref<Store> store) const;
/**
* Canonicalize a flakeref for the purpose of comparing "old" and
* "new" `original` fields in lock files.
*/
FlakeRef canonicalize() const;
};
std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);

View file

@ -32,6 +32,7 @@ suites += {
'symlink-paths.sh',
'debugger.sh',
'source-paths.sh',
'old-lockfiles.sh',
],
'workdir': meson.current_source_dir(),
}

View file

@ -0,0 +1,60 @@
#!/usr/bin/env bash
source ./common.sh
requireGit
repo="$TEST_ROOT/repo"
createGitRepo "$repo"
cat > "$repo/flake.nix" <<EOF
{
inputs = {
dependency.url = "git+file:///no-such-path?dir=subdir";
};
outputs = { dependency, self }: {
hi = dependency.an_output;
};
}
EOF
cat > "$repo/flake.lock" <<EOF
{
"nodes": {
"dependency": {
"locked": {
"dir": "subdir",
"lastModified": 1746721011,
"narHash": "sha256-9aIDvIdyHAfQyvT5SwPgYxUUhf1GwQVAWq+qa5LcEQE=",
"ref": "refs/heads/master",
"rev": "432058dbfc82b0369bc9cce440e4af2aece52b54",
"revCount": 1,
"type": "git",
"url": "file:///no-such-path?dir=subdir"
},
"original": {
"dir": "subdir",
"type": "git",
"url": "file:///no-such-path?dir=subdir"
}
},
"root": {
"inputs": {
"dependency": "dependency"
}
}
},
"root": "root",
"version": 7
}
EOF
git -C "$repo" add flake.nix flake.lock
git -C "$repo" commit -a -m foo
cp "$repo/flake.lock" "$repo/flake.lock.old"
nix flake lock "$repo"
cmp "$repo/flake.lock" "$repo/flake.lock.old"