From 92d90e2aebd75648afaf379750969dd882d59a62 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 11 Jun 2025 22:23:28 +0200 Subject: [PATCH 1/6] Run the Nix test suite with lazy trees enabled --- flake.nix | 6 ++++++ tests/functional/common/init.sh | 1 + tests/functional/package.nix | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/flake.nix b/flake.nix index b5fa93e58..451068f5d 100644 --- a/flake.nix +++ b/flake.nix @@ -220,6 +220,12 @@ ''; repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { }; + lazyTrees = + nixpkgsFor.${system}.native.nixComponents2.nix-functional-tests.override { + pname = "nix-lazy-trees-tests"; + lazyTrees = true; + }; + /** Checks for our packaging expressions. This shouldn't build anything significant; just check that things diff --git a/tests/functional/common/init.sh b/tests/functional/common/init.sh index 6e9bffec5..7f28a09d7 100755 --- a/tests/functional/common/init.sh +++ b/tests/functional/common/init.sh @@ -54,6 +54,7 @@ flake-registry = $TEST_ROOT/registry.json show-trace = true include nix.conf.extra trusted-users = $(whoami) +${_NIX_TEST_EXTRA_CONFIG:-} EOF cat > "$NIX_CONF_DIR"/nix.conf.extra < Date: Wed, 11 Jun 2025 22:30:57 +0200 Subject: [PATCH 2/6] Fix flakes test with lazy trees enabled --- tests/functional/flakes/flakes.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 0a52ba08c..e335fe6f3 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -69,7 +69,9 @@ nix flake metadata "$flake1Dir" | grepQuiet 'URL:.*flake1.*' # Test 'nix flake metadata --json'. json=$(nix flake metadata flake1 --json | jq .) [[ $(echo "$json" | jq -r .description) = 'Bla bla' ]] -[[ -d $(echo "$json" | jq -r .path) ]] +if [[ $(nix config show lazy-trees) = false ]]; then + [[ -d $(echo "$json" | jq -r .path) ]] +fi [[ $(echo "$json" | jq -r .lastModified) = $(git -C "$flake1Dir" log -n1 --format=%ct) ]] hash1=$(echo "$json" | jq -r .revision) [[ -n $(echo "$json" | jq -r .fingerprint) ]] @@ -161,7 +163,11 @@ expect 1 nix build -o "$TEST_ROOT/result" "$flake2Dir#bar" --no-update-lock-file nix build -o "$TEST_ROOT/result" "$flake2Dir#bar" --commit-lock-file [[ -e "$flake2Dir/flake.lock" ]] [[ -z $(git -C "$flake2Dir" diff main || echo failed) ]] -[[ $(jq --indent 0 . < "$flake2Dir/flake.lock") =~ ^'{"nodes":{"flake1":{"locked":{"lastModified":'.*',"narHash":"sha256-'.*'","ref":"refs/heads/master","rev":"'.*'","revCount":2,"type":"git","url":"file:///'.*'"},"original":{"id":"flake1","type":"indirect"}},"root":{"inputs":{"flake1":"flake1"}}},"root":"root","version":7}'$ ]] +if [[ $(nix config show lazy-trees) = false ]]; then + [[ $(jq --indent 0 . < "$flake2Dir/flake.lock") =~ ^'{"nodes":{"flake1":{"locked":{"lastModified":'.*',"narHash":"sha256-'.*'","ref":"refs/heads/master","rev":"'.*'","revCount":2,"type":"git","url":"file:///'.*'"},"original":{"id":"flake1","type":"indirect"}},"root":{"inputs":{"flake1":"flake1"}}},"root":"root","version":7}'$ ]] +else + [[ $(jq --indent 0 . < "$flake2Dir/flake.lock") =~ ^'{"nodes":{"flake1":{"locked":{"lastModified":'.*',"ref":"refs/heads/master","rev":"'.*'","revCount":2,"type":"git","url":"file:///'.*'"},"original":{"id":"flake1","type":"indirect"}},"root":{"inputs":{"flake1":"flake1"}}},"root":"root","version":7}'$ ]] +fi # Rerunning the build should not change the lockfile. nix build -o "$TEST_ROOT/result" "$flake2Dir#bar" From b067e6566f97c3b01f7321a19c317e6909a5380c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Jun 2025 15:54:34 +0200 Subject: [PATCH 3/6] Git fetcher: Do not consider a null revision (i.e. workdir) to be locked --- src/libfetchers/git.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 7730e0db4..2825b72ab 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -882,7 +882,8 @@ struct GitInputScheme : InputScheme bool isLocked(const Input & input) const override { - return (bool) input.getRev(); + auto rev = input.getRev(); + return rev && rev != nullRev; } }; From fca291afc358e4f1c9565dd236db1d0cc87fef24 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Jun 2025 16:00:29 +0200 Subject: [PATCH 4/6] Fix NAR hash checking for fetchGit with lazy tees If a NAR hash is specified, we should probably check it. Unfortunately, for now this has the side effect of forcing NAR hash checking of any input that has a NAR hash. --- src/libexpr/paths.cc | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index 40c0a23b6..d85f00470 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -77,25 +77,28 @@ StorePath EvalState::mountInput( allowPath(storePath); // FIXME: should just whitelist the entire virtual store + std::optional _narHash; + + auto getNarHash = [&]() + { + if (!_narHash) + // FIXME: use fetchToStore to make it cache this + _narHash = accessor->hashPath(CanonPath::root); + return _narHash; + }; + storeFS->mount(CanonPath(store->printStorePath(storePath)), accessor); - if (requireLockable && (!settings.lazyTrees || !input.isLocked()) && !input.getNarHash()) { - // FIXME: use fetchToStore to make it cache this - auto narHash = accessor->hashPath(CanonPath::root); - input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); - } + if (requireLockable && (!settings.lazyTrees || !input.isLocked()) && !input.getNarHash()) + input.attrs.insert_or_assign("narHash", getNarHash()->to_string(HashFormat::SRI, true)); - // FIXME: what to do with the NAR hash in lazy mode? - if (!settings.lazyTrees && originalInput.getNarHash()) { - auto expected = originalInput.computeStorePath(*store); - if (storePath != expected) - throw Error( - (unsigned int) 102, - "NAR hash mismatch in input '%s', expected '%s' but got '%s'", - originalInput.to_string(), - store->printStorePath(storePath), - store->printStorePath(expected)); - } + if (originalInput.getNarHash() && *getNarHash() != *originalInput.getNarHash()) + throw Error( + (unsigned int) 102, + "NAR hash mismatch in input '%s', expected '%s' but got '%s'", + originalInput.to_string(), + getNarHash()->to_string(HashFormat::SRI, true), + originalInput.getNarHash()->to_string(HashFormat::SRI, true)); return storePath; } From 6477d7c2ca3ff84f9d1b502d4d62bddfe3b77b0f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Jun 2025 16:11:54 +0200 Subject: [PATCH 5/6] mountInput(): Optimize getting the NAR hash for real store paths --- src/libexpr/paths.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index d85f00470..bdf817e3b 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -81,9 +81,13 @@ StorePath EvalState::mountInput( auto getNarHash = [&]() { - if (!_narHash) - // FIXME: use fetchToStore to make it cache this - _narHash = accessor->hashPath(CanonPath::root); + if (!_narHash) { + if (store->isValidPath(storePath)) + _narHash = store->queryPathInfo(storePath)->narHash; + else + // FIXME: use fetchToStore to make it cache this + _narHash = accessor->hashPath(CanonPath::root); + } return _narHash; }; From 279a6b18dba633a63afd69c8917833845db0c204 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Jun 2025 16:13:28 +0200 Subject: [PATCH 6/6] Formatting --- flake.nix | 9 ++++----- src/libexpr/paths.cc | 3 +-- tests/functional/package.nix | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/flake.nix b/flake.nix index 451068f5d..0207134cd 100644 --- a/flake.nix +++ b/flake.nix @@ -220,11 +220,10 @@ ''; repl-completion = nixpkgsFor.${system}.native.callPackage ./tests/repl-completion.nix { }; - lazyTrees = - nixpkgsFor.${system}.native.nixComponents2.nix-functional-tests.override { - pname = "nix-lazy-trees-tests"; - lazyTrees = true; - }; + lazyTrees = nixpkgsFor.${system}.native.nixComponents2.nix-functional-tests.override { + pname = "nix-lazy-trees-tests"; + lazyTrees = true; + }; /** Checks for our packaging expressions. diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index bdf817e3b..65b8212e1 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -79,8 +79,7 @@ StorePath EvalState::mountInput( std::optional _narHash; - auto getNarHash = [&]() - { + auto getNarHash = [&]() { if (!_narHash) { if (store->isValidPath(storePath)) _narHash = store->queryPathInfo(storePath)->narHash; diff --git a/tests/functional/package.nix b/tests/functional/package.nix index 3185cdf9a..799026ebe 100644 --- a/tests/functional/package.nix +++ b/tests/functional/package.nix @@ -28,7 +28,7 @@ test-daemon ? null, # Whether to run tests with lazy trees enabled. - lazyTrees ? false + lazyTrees ? false, }: let