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

Move mountInput into EvalState

This commit is contained in:
Eelco Dolstra 2025-04-23 13:52:22 +02:00
parent ff85b347b8
commit 182edb4dee
7 changed files with 48 additions and 60 deletions

View file

@ -36,6 +36,7 @@ class Store;
namespace fetchers { namespace fetchers {
struct Settings; struct Settings;
struct InputCache; struct InputCache;
struct Input;
} }
struct EvalSettings; struct EvalSettings;
class EvalState; class EvalState;
@ -450,6 +451,15 @@ public:
void checkURI(const std::string & uri); void checkURI(const std::string & uri);
/**
* Mount an input on the Nix store.
*/
StorePath mountInput(
fetchers::Input & input,
const fetchers::Input & originalInput,
ref<SourceAccessor> accessor,
bool requireLockable);
/** /**
* Parse a Nix expression from the specified file. * Parse a Nix expression from the specified file.
*/ */

View file

@ -67,4 +67,27 @@ std::string EvalState::computeBaseName(const SourcePath & path)
return std::string(path.baseName()); return std::string(path.baseName());
} }
StorePath EvalState::mountInput(
fetchers::Input & input, const fetchers::Input & originalInput, ref<SourceAccessor> 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;
}
} }

View file

@ -204,11 +204,7 @@ static void fetchTree(
auto cachedInput = state.inputCache->getAccessor(state.store, input, false); auto cachedInput = state.inputCache->getAccessor(state.store, input, false);
auto storePath = StorePath::random(input.getName()); auto storePath = state.mountInput(cachedInput.lockedInput, input, cachedInput.accessor, true);
state.allowPath(storePath);
state.storeFS->mount(CanonPath(state.store->printStorePath(storePath)), cachedInput.accessor);
emitTreeAttrs(state, storePath, cachedInput.lockedInput, v, params.emptyRevFallback, false); emitTreeAttrs(state, storePath, cachedInput.lockedInput, v, params.emptyRevFallback, false);
} }

View file

@ -26,33 +26,6 @@ using namespace fetchers;
namespace flake { namespace flake {
static StorePath mountInput(
EvalState & state,
fetchers::Input & input,
const fetchers::Input & originalInput,
ref<SourceAccessor> 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) static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos)
{ {
if (value.isThunk() && value.isTrivial()) if (value.isThunk() && value.isTrivial())
@ -350,7 +323,7 @@ static Flake getFlake(
const FlakeRef & originalRef, const FlakeRef & originalRef,
bool useRegistries, bool useRegistries,
const InputAttrPath & lockRootAttrPath, const InputAttrPath & lockRootAttrPath,
CopyMode copyMode) bool requireLockable)
{ {
// Fetch a lazy tree first. // Fetch a lazy tree first.
auto cachedInput = state.inputCache->getAccessor(state.store, originalRef.input, useRegistries); auto cachedInput = state.inputCache->getAccessor(state.store, originalRef.input, useRegistries);
@ -376,13 +349,13 @@ static Flake getFlake(
// Re-parse flake.nix from the store. // Re-parse flake.nix from the store.
return readFlake( return readFlake(
state, originalRef, resolvedRef, lockedRef, 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); 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( static LockFile readLockFile(
@ -404,7 +377,7 @@ LockedFlake lockFlake(
{ {
auto useRegistries = lockFlags.useRegistries.value_or(settings.useRegistries); 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) { if (lockFlags.applyNixConfig) {
flake.config.apply(settings); flake.config.apply(settings);
@ -449,13 +422,6 @@ LockedFlake lockFlake(
explicitCliOverrides.insert(i.first); 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; LockFile newLockFile;
std::vector<FlakeRef> parents; std::vector<FlakeRef> parents;
@ -586,7 +552,7 @@ LockedFlake lockFlake(
if (auto resolvedPath = resolveRelativePath()) { if (auto resolvedPath = resolveRelativePath()) {
return readFlake(state, ref, ref, ref, *resolvedPath, inputAttrPath); return readFlake(state, ref, ref, ref, *resolvedPath, inputAttrPath);
} else { } 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); auto lockedRef = FlakeRef(std::move(cachedInput.lockedInput), input.ref->subdir);
return { 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 lockedRef
}; };
} }
@ -851,7 +817,7 @@ LockedFlake lockFlake(
repo, so we should re-read it. FIXME: we could repo, so we should re-read it. FIXME: we could
also just clear the 'rev' field... */ also just clear the 'rev' field... */
auto prevLockedRef = flake.lockedRef; auto prevLockedRef = flake.lockedRef;
flake = getFlake(state, topRef, useRegistries, lockFlags.copyMode); flake = getFlake(state, topRef, useRegistries, lockFlags.requireLockable);
if (lockFlags.commitLockFile && if (lockFlags.commitLockFile &&
flake.lockedRef.input.getRev() && flake.lockedRef.input.getRev() &&

View file

@ -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( Flake getFlake(
EvalState & state, EvalState & state,
const FlakeRef & flakeRef, const FlakeRef & flakeRef,
bool useRegistries, bool useRegistries,
CopyMode copyMode = CopyMode::RequireLockable); bool requireLockable = true);
/** /**
* Fingerprint of a locked flake; used as a cache key. * Fingerprint of a locked flake; used as a cache key.
@ -228,7 +221,7 @@ struct LockFlags
/** /**
* Whether to require a locked input. * Whether to require a locked input.
*/ */
CopyMode copyMode = CopyMode::RequireLockable; bool requireLockable = true;
}; };
LockedFlake lockFlake( LockedFlake lockFlake(

View file

@ -134,7 +134,7 @@ public:
lockFlags.recreateLockFile = updateAll; lockFlags.recreateLockFile = updateAll;
lockFlags.writeLockFile = true; lockFlags.writeLockFile = true;
lockFlags.applyNixConfig = true; lockFlags.applyNixConfig = true;
lockFlags.copyMode = CopyMode::Lazy; lockFlags.requireLockable = false;
lockFlake(); lockFlake();
} }
@ -167,7 +167,7 @@ struct CmdFlakeLock : FlakeCommand
lockFlags.writeLockFile = true; lockFlags.writeLockFile = true;
lockFlags.failOnUnlocked = true; lockFlags.failOnUnlocked = true;
lockFlags.applyNixConfig = true; lockFlags.applyNixConfig = true;
lockFlags.copyMode = CopyMode::Lazy; lockFlags.requireLockable = false;
lockFlake(); lockFlake();
} }
@ -214,7 +214,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
void run(nix::ref<nix::Store> store) override void run(nix::ref<nix::Store> store) override
{ {
lockFlags.copyMode = CopyMode::Lazy; lockFlags.requireLockable = false;
auto lockedFlake = lockFlake(); auto lockedFlake = lockFlake();
auto & flake = lockedFlake.flake; auto & flake = lockedFlake.flake;

View file

@ -303,7 +303,7 @@ echo foo > "$empty/x"
git -C "$empty" add 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. # Test a repo with an empty commit.
git -C "$empty" rm -f x git -C "$empty" rm -f x