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

Devirtualize double-copied paths

Borrowed from the original lazy-trees branch.
This commit is contained in:
Eelco Dolstra 2025-04-15 17:44:56 +02:00
parent e099a5bc67
commit 0c0dda3b29
4 changed files with 33 additions and 2 deletions

View file

@ -2317,6 +2317,9 @@ BackedStringView EvalState::coerceToString(
} }
if (v.type() == nPath) { if (v.type() == nPath) {
// FIXME: instead of copying the path to the store, we could
// return a virtual store path that lazily copies the path to
// the store in devirtualize().
return return
!canonicalizePath && !copyToStore !canonicalizePath && !copyToStore
? // FIXME: hack to preserve path literals that end in a ? // FIXME: hack to preserve path literals that end in a
@ -2406,7 +2409,7 @@ StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePat
*store, *store,
path.resolveSymlinks(SymlinkResolution::Ancestors), path.resolveSymlinks(SymlinkResolution::Ancestors),
settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy, settings.readOnlyMode ? FetchMode::DryRun : FetchMode::Copy,
path.baseName(), computeBaseName(path),
ContentAddressMethod::Raw::NixArchive, ContentAddressMethod::Raw::NixArchive,
nullptr, nullptr,
repair); repair);

View file

@ -586,6 +586,19 @@ public:
StorePath copyPathToStore(NixStringContext & context, const SourcePath & path); StorePath copyPathToStore(NixStringContext & context, const SourcePath & path);
/**
* Compute the base name for a `SourcePath`. For non-store paths,
* this is just `SourcePath::baseName()`. But for store paths, for
* backwards compatibility, it needs to be `<hash>-source`,
* i.e. as if the path were copied to the Nix store. This results
* in a "double-copied" store path like
* `/nix/store/<hash1>-<hash2>-source`. We don't need to
* materialize /nix/store/<hash2>-source though. Still, this
* requires reading/hashing the path twice.
*/
std::string computeBaseName(const SourcePath & path);
/** /**
* Path coercion. * Path coercion.
* *

View file

@ -52,4 +52,19 @@ std::string EvalState::devirtualize(std::string_view s, const NixStringContext &
return rewriteStrings(std::string(s), rewrites); return rewriteStrings(std::string(s), rewrites);
} }
std::string EvalState::computeBaseName(const SourcePath & path)
{
if (path.accessor == rootFS) {
if (auto storePath = store->maybeParseStorePath(path.path.abs())) {
warn(
"Performing inefficient double copy of path '%s' to the store. "
"This can typically be avoided by rewriting an attribute like `src = ./.` "
"to `src = builtins.path { path = ./.; name = \"source\"; }`.",
path);
return std::string(fetchToStore(*store, path, FetchMode::DryRun).to_string());
}
}
return std::string(path.baseName());
}
} }

View file

@ -2539,7 +2539,7 @@ static void prim_filterSource(EvalState & state, const PosIdx pos, Value * * arg
"while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'"); "while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'");
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.filterSource"); state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.filterSource");
addPath(state, pos, path.baseName(), path, args[0], ContentAddressMethod::Raw::NixArchive, std::nullopt, v, context); addPath(state, pos, state.computeBaseName(path), path, args[0], ContentAddressMethod::Raw::NixArchive, std::nullopt, v, context);
} }
static RegisterPrimOp primop_filterSource({ static RegisterPrimOp primop_filterSource({