From 9d87ab1dc8b3e200c01e04e5fb6c8381b9a04301 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 24 Apr 2025 16:03:49 +0200 Subject: [PATCH] Add a setting to enable lazy trees --- src/libexpr/include/nix/expr/eval-settings.hh | 5 +++++ src/libexpr/paths.cc | 11 +++++------ tests/functional/flakes/flakes.sh | 3 ++- tests/functional/flakes/unlocked-override.sh | 3 ++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libexpr/include/nix/expr/eval-settings.hh b/src/libexpr/include/nix/expr/eval-settings.hh index fb482568a..6e5bbca20 100644 --- a/src/libexpr/include/nix/expr/eval-settings.hh +++ b/src/libexpr/include/nix/expr/eval-settings.hh @@ -247,6 +247,11 @@ struct EvalSettings : Config This option can be enabled by setting `NIX_ABORT_ON_WARN=1` in the environment. )"}; + + Setting lazyTrees{this, false, "lazy-trees", + R"( + If set to true, flakes and trees fetched by [`builtins.fetchTree`](@docroot@/language/builtins.md#builtins-fetchTree) are only copied to the Nix store when they're used as a dependency of a derivation. This avoids copying (potentially large) source trees unnecessarily. + )"}; }; /** diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index 8e1c68e9a..451962636 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -70,7 +70,8 @@ std::string EvalState::computeBaseName(const SourcePath & path) StorePath EvalState::mountInput( fetchers::Input & input, const fetchers::Input & originalInput, ref accessor, bool requireLockable) { - auto storePath = StorePath::random(input.getName()); + auto storePath = settings.lazyTrees ? StorePath::random(input.getName()) + : fetchToStore(*store, accessor, FetchMode::Copy, input.getName()); allowPath(storePath); // FIXME: should just whitelist the entire virtual store @@ -81,11 +82,9 @@ StorePath EvalState::mountInput( input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); } - // FIXME: check NAR hash - -#if 0 - assert(!originalInput.getNarHash() || storePath == originalInput.computeStorePath(*store)); -#endif + // FIXME: what to do with the NAR hash in lazy mode? + if (!settings.lazyTrees) + assert(!originalInput.getNarHash() || storePath == originalInput.computeStorePath(*store)); return storePath; } diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 0fcdf0b30..c8cd5f138 100755 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -75,7 +75,8 @@ hash1=$(echo "$json" | jq -r .revision) echo foo > "$flake1Dir/foo" git -C "$flake1Dir" add $flake1Dir/foo -[[ $(_NIX_TEST_FAIL_ON_LARGE_PATH=1 nix flake metadata flake1 --json --refresh --warn-large-path-threshold 1 | jq -r .dirtyRevision) == "$hash1-dirty" ]] +[[ $(nix flake metadata flake1 --json --refresh | jq -r .dirtyRevision) == "$hash1-dirty" ]] +#[[ $(_NIX_TEST_FAIL_ON_LARGE_PATH=1 nix flake metadata flake1 --json --refresh --warn-large-path-threshold 1 | jq -r .dirtyRevision) == "$hash1-dirty" ]] [[ "$(nix flake metadata flake1 --json | jq -r .fingerprint)" != null ]] echo -n '# foo' >> "$flake1Dir/flake.nix" diff --git a/tests/functional/flakes/unlocked-override.sh b/tests/functional/flakes/unlocked-override.sh index 9d8d569f1..73784b4e8 100755 --- a/tests/functional/flakes/unlocked-override.sh +++ b/tests/functional/flakes/unlocked-override.sh @@ -35,7 +35,8 @@ echo 456 > "$flake1Dir"/x.nix expectStderr 1 nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" | grepQuiet "Will not write lock file.*because it has an unlocked input" -_NIX_TEST_FAIL_ON_LARGE_PATH=1 nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" --allow-dirty-locks --warn-large-path-threshold 1 +nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" --allow-dirty-locks +#_NIX_TEST_FAIL_ON_LARGE_PATH=1 nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" --allow-dirty-locks --warn-large-path-threshold 1 # Using a lock file with a dirty lock does not require --allow-dirty-locks, but should print a warning. expectStderr 0 nix eval "$flake2Dir#x" |