1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 10:11:47 +02:00

Move getAccessorCached() to InputCache

Also, make fetchTree use InputCache.
This commit is contained in:
Eelco Dolstra 2025-04-09 23:06:03 +02:00
parent 3bbf917707
commit dd15c8a20d
4 changed files with 70 additions and 66 deletions

View file

@ -10,6 +10,7 @@
#include "nix/util/url.hh" #include "nix/util/url.hh"
#include "nix/expr/value-to-json.hh" #include "nix/expr/value-to-json.hh"
#include "nix/fetchers/fetch-to-store.hh" #include "nix/fetchers/fetch-to-store.hh"
#include "nix/fetchers/input-cache.hh"
#include "nix/util/mounted-source-accessor.hh" #include "nix/util/mounted-source-accessor.hh"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@ -201,16 +202,15 @@ static void fetchTree(
throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string()); throw Error("input '%s' is not allowed to use the '__final' attribute", input.to_string());
} }
// FIXME: use fetchOrSubstituteTree(). auto cachedInput = fetchers::InputCache::getCache()->getAccessor(state.store, input, false);
auto [accessor, lockedInput] = input.getAccessor(state.store);
auto storePath = StorePath::random(input.getName()); auto storePath = StorePath::random(input.getName());
state.allowPath(storePath); state.allowPath(storePath);
state.storeFS->mount(CanonPath(state.store->printStorePath(storePath)), accessor); state.storeFS->mount(CanonPath(state.store->printStorePath(storePath)), cachedInput.accessor);
emitTreeAttrs(state, storePath, lockedInput, 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) static void prim_fetchTree(EvalState & state, const PosIdx pos, Value * * args, Value & v)

View file

@ -2,14 +2,23 @@
namespace nix::fetchers { namespace nix::fetchers {
struct CachedInput
{
Input lockedInput;
ref<SourceAccessor> accessor;
};
struct InputCache struct InputCache
{ {
struct CachedResult
{
ref<SourceAccessor> accessor;
Input resolvedInput;
Input lockedInput;
};
CachedResult getAccessor(ref<Store> store, const Input & originalInput, bool useRegistries);
struct CachedInput
{
Input lockedInput;
ref<SourceAccessor> accessor;
};
virtual std::optional<CachedInput> lookup(const Input & originalInput) const = 0; virtual std::optional<CachedInput> lookup(const Input & originalInput) const = 0;
virtual void upsert(Input key, CachedInput cachedInput) = 0; virtual void upsert(Input key, CachedInput cachedInput) = 0;

View file

@ -1,8 +1,48 @@
#include "nix/fetchers/input-cache.hh" #include "nix/fetchers/input-cache.hh"
#include "nix/fetchers/registry.hh"
#include "nix/util/sync.hh" #include "nix/util/sync.hh"
#include "nix/util/source-path.hh"
namespace nix::fetchers { namespace nix::fetchers {
InputCache::CachedResult InputCache::getAccessor(ref<Store> store, const Input & originalInput, bool useRegistries)
{
auto fetched = lookup(originalInput);
Input resolvedInput = originalInput;
if (!fetched) {
if (originalInput.isDirect()) {
auto [accessor, lockedInput] = originalInput.getAccessor(store);
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
} else {
if (useRegistries) {
auto [res, extraAttrs] =
lookupInRegistries(store, originalInput, [](fetchers::Registry::RegistryType type) {
/* Only use the global registry and CLI flags
to resolve indirect flakerefs. */
return type == fetchers::Registry::Flag || type == fetchers::Registry::Global;
});
resolvedInput = std::move(res);
fetched = lookup(resolvedInput);
if (!fetched) {
auto [accessor, lockedInput] = resolvedInput.getAccessor(store);
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
}
upsert(resolvedInput, *fetched);
} else {
throw Error(
"'%s' is an indirect flake reference, but registry lookups are not allowed",
originalInput.to_string());
}
}
upsert(originalInput, *fetched);
}
debug("got tree '%s' from '%s'", fetched->accessor, fetched->lockedInput.to_string());
return {fetched->accessor, resolvedInput, fetched->lockedInput};
}
struct InputCacheImpl : InputCache struct InputCacheImpl : InputCache
{ {
Sync<std::map<Input, CachedInput>> cache_; Sync<std::map<Input, CachedInput>> cache_;

View file

@ -26,48 +26,6 @@ using namespace fetchers;
namespace flake { namespace flake {
static std::tuple<ref<SourceAccessor>, Input, Input> getAccessorCached(
EvalState & state,
const Input & originalInput,
bool useRegistries)
{
auto inputCache = InputCache::getCache();
auto fetched = inputCache->lookup(originalInput);
Input resolvedInput = originalInput;
if (!fetched) {
if (originalInput.isDirect()) {
auto [accessor, lockedInput] = originalInput.getAccessor(state.store);
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
} else {
if (useRegistries) {
auto [res, extraAttrs] = lookupInRegistries(state.store, originalInput,
[](fetchers::Registry::RegistryType type) {
/* Only use the global registry and CLI flags
to resolve indirect flakerefs. */
return type == fetchers::Registry::Flag || type == fetchers::Registry::Global;
});
resolvedInput = std::move(res);
fetched = inputCache->lookup(resolvedInput);
if (!fetched) {
auto [accessor, lockedInput] = resolvedInput.getAccessor(state.store);
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
}
inputCache->upsert(resolvedInput, *fetched);
}
else {
throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalInput.to_string());
}
}
inputCache->upsert(originalInput, *fetched);
}
debug("got tree '%s' from '%s'", fetched->accessor, fetched->lockedInput.to_string());
return {fetched->accessor, resolvedInput, fetched->lockedInput};
}
static StorePath mountInput( static StorePath mountInput(
EvalState & state, EvalState & state,
fetchers::Input & input, fetchers::Input & input,
@ -395,14 +353,13 @@ static Flake getFlake(
CopyMode copyMode) CopyMode copyMode)
{ {
// Fetch a lazy tree first. // Fetch a lazy tree first.
auto [accessor, resolvedInput, lockedInput] = getAccessorCached( auto cachedInput = fetchers::InputCache::getCache()->getAccessor(state.store, originalRef.input, useRegistries);
state, originalRef.input, useRegistries);
auto resolvedRef = FlakeRef(std::move(resolvedInput), originalRef.subdir); auto resolvedRef = FlakeRef(std::move(cachedInput.resolvedInput), originalRef.subdir);
auto lockedRef = FlakeRef(std::move(lockedInput), originalRef.subdir); auto lockedRef = FlakeRef(std::move(cachedInput.lockedInput), originalRef.subdir);
// Parse/eval flake.nix to get at the input.self attributes. // Parse/eval flake.nix to get at the input.self attributes.
auto flake = readFlake(state, originalRef, resolvedRef, lockedRef, {accessor}, lockRootAttrPath); auto flake = readFlake(state, originalRef, resolvedRef, lockedRef, {cachedInput.accessor}, lockRootAttrPath);
// Re-fetch the tree if necessary. // Re-fetch the tree if necessary.
auto newLockedRef = applySelfAttrs(lockedRef, flake); auto newLockedRef = applySelfAttrs(lockedRef, flake);
@ -411,16 +368,15 @@ static Flake getFlake(
debug("refetching input '%s' due to self attribute", newLockedRef); debug("refetching input '%s' due to self attribute", newLockedRef);
// FIXME: need to remove attrs that are invalidated by the changed input attrs, such as 'narHash'. // FIXME: need to remove attrs that are invalidated by the changed input attrs, such as 'narHash'.
newLockedRef.input.attrs.erase("narHash"); newLockedRef.input.attrs.erase("narHash");
auto [accessor2, resolvedInput2, lockedInput2] = getAccessorCached( auto cachedInput2 = fetchers::InputCache::getCache()->getAccessor(state.store, newLockedRef.input, useRegistries);
state, newLockedRef.input, false); cachedInput.accessor = cachedInput2.accessor;
accessor = accessor2; lockedRef = FlakeRef(std::move(cachedInput2.lockedInput), newLockedRef.subdir);
lockedRef = FlakeRef(std::move(lockedInput2), newLockedRef.subdir);
} }
// 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, accessor, copyMode)), state.storePath(mountInput(state, lockedRef.input, originalRef.input, cachedInput.accessor, copyMode)),
lockRootAttrPath); lockRootAttrPath);
} }
@ -778,13 +734,12 @@ LockedFlake lockFlake(
if (auto resolvedPath = resolveRelativePath()) { if (auto resolvedPath = resolveRelativePath()) {
return {*resolvedPath, *input.ref}; return {*resolvedPath, *input.ref};
} else { } else {
auto [accessor, resolvedInput, lockedInput] = getAccessorCached( auto cachedInput = fetchers::InputCache::getCache()->getAccessor(state.store, input.ref->input, useRegistries);
state, input.ref->input, useRegistries);
auto lockedRef = FlakeRef(std::move(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, accessor, inputCopyMode)), state.storePath(mountInput(state, lockedRef.input, input.ref->input, cachedInput.accessor, inputCopyMode)),
lockedRef lockedRef
}; };
} }