From 182edb4dee637f37edfc1a027f1b95f30c66bc00 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 23 Apr 2025 13:52:22 +0200 Subject: [PATCH] Move mountInput into EvalState --- src/libexpr/include/nix/expr/eval.hh | 10 +++++ src/libexpr/paths.cc | 23 ++++++++++++ src/libexpr/primops/fetchTree.cc | 6 +-- src/libflake/flake/flake.cc | 50 ++++--------------------- src/libflake/include/nix/flake/flake.hh | 11 +----- src/nix/flake.cc | 6 +-- tests/functional/fetchGit.sh | 2 +- 7 files changed, 48 insertions(+), 60 deletions(-) diff --git a/src/libexpr/include/nix/expr/eval.hh b/src/libexpr/include/nix/expr/eval.hh index 3249b50a0..d82baddb1 100644 --- a/src/libexpr/include/nix/expr/eval.hh +++ b/src/libexpr/include/nix/expr/eval.hh @@ -36,6 +36,7 @@ class Store; namespace fetchers { struct Settings; struct InputCache; +struct Input; } struct EvalSettings; class EvalState; @@ -450,6 +451,15 @@ public: void checkURI(const std::string & uri); + /** + * Mount an input on the Nix store. + */ + StorePath mountInput( + fetchers::Input & input, + const fetchers::Input & originalInput, + ref accessor, + bool requireLockable); + /** * Parse a Nix expression from the specified file. */ diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index a27ebcae2..8e1c68e9a 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -67,4 +67,27 @@ std::string EvalState::computeBaseName(const SourcePath & path) return std::string(path.baseName()); } +StorePath EvalState::mountInput( + fetchers::Input & input, const fetchers::Input & originalInput, ref accessor, bool requireLockable) +{ + auto storePath = StorePath::random(input.getName()); + + allowPath(storePath); // FIXME: should just whitelist the entire virtual store + + storeFS->mount(CanonPath(store->printStorePath(storePath)), accessor); + + if (requireLockable && !input.isLocked() && !input.getNarHash()) { + auto narHash = accessor->hashPath(CanonPath::root); + 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 + + return storePath; +} + } diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 5d41d65c1..7dae30b6f 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -204,11 +204,7 @@ static void fetchTree( auto cachedInput = state.inputCache->getAccessor(state.store, input, false); - auto storePath = StorePath::random(input.getName()); - - state.allowPath(storePath); - - state.storeFS->mount(CanonPath(state.store->printStorePath(storePath)), cachedInput.accessor); + auto storePath = state.mountInput(cachedInput.lockedInput, input, cachedInput.accessor, true); emitTreeAttrs(state, storePath, cachedInput.lockedInput, v, params.emptyRevFallback, false); } diff --git a/src/libflake/flake/flake.cc b/src/libflake/flake/flake.cc index 299a74640..2d3fd4e07 100644 --- a/src/libflake/flake/flake.cc +++ b/src/libflake/flake/flake.cc @@ -26,33 +26,6 @@ using namespace fetchers; namespace flake { -static StorePath mountInput( - EvalState & state, - fetchers::Input & input, - const fetchers::Input & originalInput, - ref accessor, - CopyMode copyMode) -{ - auto storePath = StorePath::random(input.getName()); - - state.allowPath(storePath); // FIXME: should just whitelist the entire virtual store - - state.storeFS->mount(CanonPath(state.store->printStorePath(storePath)), accessor); - - if (copyMode == CopyMode::RequireLockable && !input.isLocked() && !input.getNarHash()) { - auto narHash = accessor->hashPath(CanonPath::root); - input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true)); - } - - // FIXME: check NAR hash - - #if 0 - assert(!originalInput.getNarHash() || storePath == originalInput.computeStorePath(*state.store)); - #endif - - return storePath; -} - static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos) { if (value.isThunk() && value.isTrivial()) @@ -350,7 +323,7 @@ static Flake getFlake( const FlakeRef & originalRef, bool useRegistries, const InputAttrPath & lockRootAttrPath, - CopyMode copyMode) + bool requireLockable) { // Fetch a lazy tree first. auto cachedInput = state.inputCache->getAccessor(state.store, originalRef.input, useRegistries); @@ -376,13 +349,13 @@ static Flake getFlake( // Re-parse flake.nix from the store. return readFlake( state, originalRef, resolvedRef, lockedRef, - state.storePath(mountInput(state, lockedRef.input, originalRef.input, cachedInput.accessor, copyMode)), + state.storePath(state.mountInput(lockedRef.input, originalRef.input, cachedInput.accessor, requireLockable)), lockRootAttrPath); } -Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistries, CopyMode copyMode) +Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool useRegistries, bool requireLockable) { - return getFlake(state, originalRef, useRegistries, {}, copyMode); + return getFlake(state, originalRef, useRegistries, {}, requireLockable); } static LockFile readLockFile( @@ -404,7 +377,7 @@ LockedFlake lockFlake( { auto useRegistries = lockFlags.useRegistries.value_or(settings.useRegistries); - auto flake = getFlake(state, topRef, useRegistries, {}, lockFlags.copyMode); + auto flake = getFlake(state, topRef, useRegistries, {}, lockFlags.requireLockable); if (lockFlags.applyNixConfig) { flake.config.apply(settings); @@ -449,13 +422,6 @@ LockedFlake lockFlake( explicitCliOverrides.insert(i.first); } - /* For locking of inputs, we require at least a NAR - hash. I.e. we can't be fully lazy. */ - auto inputCopyMode = - lockFlags.copyMode == CopyMode::Lazy - ? CopyMode::RequireLockable - : lockFlags.copyMode; - LockFile newLockFile; std::vector parents; @@ -586,7 +552,7 @@ LockedFlake lockFlake( if (auto resolvedPath = resolveRelativePath()) { return readFlake(state, ref, ref, ref, *resolvedPath, inputAttrPath); } else { - return getFlake(state, ref, useRegistries, inputAttrPath, inputCopyMode); + return getFlake(state, ref, useRegistries, inputAttrPath, true); } }; @@ -739,7 +705,7 @@ LockedFlake lockFlake( auto lockedRef = FlakeRef(std::move(cachedInput.lockedInput), input.ref->subdir); return { - state.storePath(mountInput(state, lockedRef.input, input.ref->input, cachedInput.accessor, inputCopyMode)), + state.storePath(state.mountInput(lockedRef.input, input.ref->input, cachedInput.accessor, true)), lockedRef }; } @@ -851,7 +817,7 @@ LockedFlake lockFlake( repo, so we should re-read it. FIXME: we could also just clear the 'rev' field... */ auto prevLockedRef = flake.lockedRef; - flake = getFlake(state, topRef, useRegistries, lockFlags.copyMode); + flake = getFlake(state, topRef, useRegistries, lockFlags.requireLockable); if (lockFlags.commitLockFile && flake.lockedRef.input.getRev() && diff --git a/src/libflake/include/nix/flake/flake.hh b/src/libflake/include/nix/flake/flake.hh index 35398a306..1dd55d107 100644 --- a/src/libflake/include/nix/flake/flake.hh +++ b/src/libflake/include/nix/flake/flake.hh @@ -115,18 +115,11 @@ struct Flake } }; -enum struct CopyMode { - //! Ensure that the input is locked or has a NAR hash. - RequireLockable, - //! Just return a lazy source accessor. - Lazy, -}; - Flake getFlake( EvalState & state, const FlakeRef & flakeRef, bool useRegistries, - CopyMode copyMode = CopyMode::RequireLockable); + bool requireLockable = true); /** * Fingerprint of a locked flake; used as a cache key. @@ -228,7 +221,7 @@ struct LockFlags /** * Whether to require a locked input. */ - CopyMode copyMode = CopyMode::RequireLockable; + bool requireLockable = true; }; LockedFlake lockFlake( diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 26626b020..9f63fabc4 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -134,7 +134,7 @@ public: lockFlags.recreateLockFile = updateAll; lockFlags.writeLockFile = true; lockFlags.applyNixConfig = true; - lockFlags.copyMode = CopyMode::Lazy; + lockFlags.requireLockable = false; lockFlake(); } @@ -167,7 +167,7 @@ struct CmdFlakeLock : FlakeCommand lockFlags.writeLockFile = true; lockFlags.failOnUnlocked = true; lockFlags.applyNixConfig = true; - lockFlags.copyMode = CopyMode::Lazy; + lockFlags.requireLockable = false; lockFlake(); } @@ -214,7 +214,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON void run(nix::ref store) override { - lockFlags.copyMode = CopyMode::Lazy; + lockFlags.requireLockable = false; auto lockedFlake = lockFlake(); auto & flake = lockedFlake.flake; diff --git a/tests/functional/fetchGit.sh b/tests/functional/fetchGit.sh index 283833e58..baa09b60b 100755 --- a/tests/functional/fetchGit.sh +++ b/tests/functional/fetchGit.sh @@ -303,7 +303,7 @@ echo foo > "$empty/x" git -C "$empty" add x -[[ $(nix eval --impure --expr "builtins.removeAttrs (builtins.fetchGit $empty) [\"outPath\"]") = '{ lastModified = 0; lastModifiedDate = "19700101000000"; rev = "0000000000000000000000000000000000000000"; revCount = 0; shortRev = "0000000"; submodules = false; }' ]] +[[ $(nix eval --impure --expr "builtins.removeAttrs (builtins.fetchGit $empty) [\"outPath\"]") = '{ lastModified = 0; lastModifiedDate = "19700101000000"; narHash = "sha256-wzlAGjxKxpaWdqVhlq55q5Gxo4Bf860+kLeEa/v02As="; rev = "0000000000000000000000000000000000000000"; revCount = 0; shortRev = "0000000"; submodules = false; }' ]] # Test a repo with an empty commit. git -C "$empty" rm -f x