1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 03:56:01 +01:00

Merge pull request #14050 from NixOS/fix-fetch-to-store-caching

Fix fetchToStore caching
This commit is contained in:
Eelco Dolstra 2025-10-06 19:39:41 +02:00 committed by GitHub
commit 1e709554d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 188 additions and 92 deletions

View file

@ -236,24 +236,17 @@ EvalState::EvalState(
{CanonPath(store->storeDir), store->getFSAccessor(settings.pureEval)},
}))
, rootFS([&] {
auto accessor = [&]() -> decltype(rootFS) {
/* In pure eval mode, we provide a filesystem that only
contains the Nix store. */
if (settings.pureEval)
return storeFS;
/* In pure eval mode, we provide a filesystem that only
contains the Nix store.
/* If we have a chroot store and pure eval is not enabled,
use a union accessor to make the chroot store available
at its logical location while still having the underlying
directory available. This is necessary for instance if
we're evaluating a file from the physical /nix/store
while using a chroot store. */
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
if (store->storeDir != realStoreDir)
return makeUnionSourceAccessor({getFSSourceAccessor(), storeFS});
return getFSSourceAccessor();
}();
Otherwise, use a union accessor to make the augmented store
available at its logical location while still having the
underlying directory available. This is necessary for
instance if we're evaluating a file from the physical
/nix/store while using a chroot store, and also for lazy
mounted fetchTree. */
auto accessor = settings.pureEval ? storeFS.cast<SourceAccessor>()
: makeUnionSourceAccessor({getFSSourceAccessor(), storeFS});
/* Apply access control if needed. */
if (settings.restrictEval || settings.pureEval)
@ -3133,6 +3126,11 @@ SourcePath EvalState::findFile(const LookupPath & lookupPath, const std::string_
auto res = (r / CanonPath(suffix)).resolveSymlinks();
if (res.pathExists())
return res;
// Backward compatibility hack: throw an exception if access
// to this path is not allowed.
if (auto accessor = res.accessor.dynamic_pointer_cast<FilteringSourceAccessor>())
accessor->checkAccess(res.path);
}
if (hasPrefix(path, "nix/"))
@ -3199,6 +3197,11 @@ std::optional<SourcePath> EvalState::resolveLookupPathPath(const LookupPath::Pat
if (path.resolveSymlinks().pathExists())
return finish(std::move(path));
else {
// Backward compatibility hack: throw an exception if access
// to this path is not allowed.
if (auto accessor = path.accessor.dynamic_pointer_cast<FilteringSourceAccessor>())
accessor->checkAccess(path.path);
logWarning({.msg = HintFmt("Nix search path entry '%1%' does not exist, ignoring", value)});
}
}

View file

@ -42,6 +42,7 @@ class Store;
namespace fetchers {
struct Settings;
struct InputCache;
struct Input;
} // namespace fetchers
struct EvalSettings;
class EvalState;
@ -575,6 +576,11 @@ public:
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);
/**
* Parse a Nix expression from the specified file.
*/

View file

@ -1,5 +1,7 @@
#include "nix/store/store-api.hh"
#include "nix/expr/eval.hh"
#include "nix/util/mounted-source-accessor.hh"
#include "nix/fetchers/fetch-to-store.hh"
namespace nix {
@ -18,4 +20,27 @@ SourcePath EvalState::storePath(const StorePath & path)
return {rootFS, CanonPath{store->printStorePath(path)}};
}
StorePath
EvalState::mountInput(fetchers::Input & input, const fetchers::Input & originalInput, ref<SourceAccessor> accessor)
{
auto storePath = fetchToStore(fetchSettings, *store, accessor, FetchMode::Copy, input.getName());
allowPath(storePath); // FIXME: should just whitelist the entire virtual store
storeFS->mount(CanonPath(store->printStorePath(storePath)), accessor);
auto narHash = store->queryPathInfo(storePath)->narHash;
input.attrs.insert_or_assign("narHash", narHash.to_string(HashFormat::SRI, true));
if (originalInput.getNarHash() && narHash != *originalInput.getNarHash())
throw Error(
(unsigned int) 102,
"NAR hash mismatch in input '%s', expected '%s' but got '%s'",
originalInput.to_string(),
narHash.to_string(HashFormat::SRI, true),
originalInput.getNarHash()->to_string(HashFormat::SRI, true));
return storePath;
}
} // namespace nix

View file

@ -10,6 +10,7 @@
#include "nix/util/url.hh"
#include "nix/expr/value-to-json.hh"
#include "nix/fetchers/fetch-to-store.hh"
#include "nix/fetchers/input-cache.hh"
#include <nlohmann/json.hpp>
@ -218,11 +219,11 @@ static void fetchTree(
throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string());
}
auto [storePath, input2] = input.fetchToStore(state.store);
auto cachedInput = state.inputCache->getAccessor(state.store, input, fetchers::UseRegistries::No);
state.allowPath(storePath);
auto storePath = state.mountInput(cachedInput.lockedInput, input, cachedInput.accessor);
emitTreeAttrs(state, storePath, input2, v, params.emptyRevFallback, false);
emitTreeAttrs(state, storePath, cachedInput.lockedInput, v, params.emptyRevFallback, false);
}
static void prim_fetchTree(EvalState & state, const PosIdx pos, Value ** args, Value & v)