1414#include " nix/store/local-fs-store.hh"
1515#include " nix/fetchers/fetch-to-store.hh"
1616#include " nix/util/memory-source-accessor.hh"
17+ #include " nix/fetchers/input-cache.hh"
1718
1819#include < nlohmann/json.hpp>
1920
@@ -23,66 +24,6 @@ using namespace flake;
2324
2425namespace flake {
2526
26- struct FetchedFlake
27- {
28- FlakeRef lockedRef;
29- ref<SourceAccessor> accessor;
30- };
31-
32- typedef std::map<FlakeRef, FetchedFlake> FlakeCache;
33-
34- static std::optional<FetchedFlake> lookupInFlakeCache (
35- const FlakeCache & flakeCache,
36- const FlakeRef & flakeRef)
37- {
38- auto i = flakeCache.find (flakeRef);
39- if (i == flakeCache.end ()) return std::nullopt ;
40- debug (" mapping '%s' to previously seen input '%s' -> '%s" ,
41- flakeRef, i->first , i->second .lockedRef );
42- return i->second ;
43- }
44-
45- static std::tuple<ref<SourceAccessor>, FlakeRef, FlakeRef> fetchOrSubstituteTree (
46- EvalState & state,
47- const FlakeRef & originalRef,
48- bool useRegistries,
49- FlakeCache & flakeCache)
50- {
51- auto fetched = lookupInFlakeCache (flakeCache, originalRef);
52- FlakeRef resolvedRef = originalRef;
53-
54- if (!fetched) {
55- if (originalRef.input .isDirect ()) {
56- auto [accessor, lockedRef] = originalRef.lazyFetch (state.store );
57- fetched.emplace (FetchedFlake{.lockedRef = lockedRef, .accessor = accessor});
58- } else {
59- if (useRegistries) {
60- resolvedRef = originalRef.resolve (
61- state.store ,
62- [](fetchers::Registry::RegistryType type) {
63- /* Only use the global registry and CLI flags
64- to resolve indirect flakerefs. */
65- return type == fetchers::Registry::Flag || type == fetchers::Registry::Global;
66- });
67- fetched = lookupInFlakeCache (flakeCache, originalRef);
68- if (!fetched) {
69- auto [accessor, lockedRef] = resolvedRef.lazyFetch (state.store );
70- fetched.emplace (FetchedFlake{.lockedRef = lockedRef, .accessor = accessor});
71- }
72- flakeCache.insert_or_assign (resolvedRef, *fetched);
73- }
74- else {
75- throw Error (" '%s' is an indirect flake reference, but registry lookups are not allowed" , originalRef);
76- }
77- }
78- flakeCache.insert_or_assign (originalRef, *fetched);
79- }
80-
81- debug (" got tree '%s' from '%s'" , fetched->accessor , fetched->lockedRef );
82-
83- return {fetched->accessor , resolvedRef, fetched->lockedRef };
84- }
85-
8627static StorePath copyInputToStore (
8728 EvalState & state,
8829 fetchers::Input & input,
@@ -397,15 +338,16 @@ static Flake getFlake(
397338 EvalState & state,
398339 const FlakeRef & originalRef,
399340 bool useRegistries,
400- FlakeCache & flakeCache,
401341 const InputAttrPath & lockRootAttrPath)
402342{
403343 // Fetch a lazy tree first.
404- auto [accessor, resolvedRef, lockedRef] = fetchOrSubstituteTree (
405- state, originalRef, useRegistries, flakeCache);
344+ auto cachedInput = state.inputCache ->getAccessor (state.store , originalRef.input , useRegistries);
345+
346+ auto resolvedRef = FlakeRef (std::move (cachedInput.resolvedInput ), originalRef.subdir );
347+ auto lockedRef = FlakeRef (std::move (cachedInput.lockedInput ), originalRef.subdir );
406348
407349 // Parse/eval flake.nix to get at the input.self attributes.
408- auto flake = readFlake (state, originalRef, resolvedRef, lockedRef, {accessor}, lockRootAttrPath);
350+ auto flake = readFlake (state, originalRef, resolvedRef, lockedRef, {cachedInput. accessor }, lockRootAttrPath);
409351
410352 // Re-fetch the tree if necessary.
411353 auto newLockedRef = applySelfAttrs (lockedRef, flake);
@@ -414,23 +356,21 @@ static Flake getFlake(
414356 debug (" refetching input '%s' due to self attribute" , newLockedRef);
415357 // FIXME: need to remove attrs that are invalidated by the changed input attrs, such as 'narHash'.
416358 newLockedRef.input .attrs .erase (" narHash" );
417- auto [accessor2, resolvedRef2, lockedRef2] = fetchOrSubstituteTree (
418- state, newLockedRef, false , flakeCache);
419- accessor = accessor2;
420- lockedRef = lockedRef2;
359+ auto cachedInput2 = state.inputCache ->getAccessor (state.store , newLockedRef.input , useRegistries);
360+ cachedInput.accessor = cachedInput2.accessor ;
361+ lockedRef = FlakeRef (std::move (cachedInput2.lockedInput ), newLockedRef.subdir );
421362 }
422363
423364 // Copy the tree to the store.
424- auto storePath = copyInputToStore (state, lockedRef.input , originalRef.input , accessor);
365+ auto storePath = copyInputToStore (state, lockedRef.input , originalRef.input , cachedInput. accessor );
425366
426367 // Re-parse flake.nix from the store.
427368 return readFlake (state, originalRef, resolvedRef, lockedRef, state.storePath (storePath), lockRootAttrPath);
428369}
429370
430371Flake getFlake (EvalState & state, const FlakeRef & originalRef, bool useRegistries)
431372{
432- FlakeCache flakeCache;
433- return getFlake (state, originalRef, useRegistries, flakeCache, {});
373+ return getFlake (state, originalRef, useRegistries, {});
434374}
435375
436376static LockFile readLockFile (
@@ -452,11 +392,9 @@ LockedFlake lockFlake(
452392{
453393 experimentalFeatureSettings.require (Xp::Flakes);
454394
455- FlakeCache flakeCache;
456-
457395 auto useRegistries = lockFlags.useRegistries .value_or (settings.useRegistries );
458396
459- auto flake = getFlake (state, topRef, useRegistries, flakeCache, {});
397+ auto flake = getFlake (state, topRef, useRegistries, {});
460398
461399 if (lockFlags.applyNixConfig ) {
462400 flake.config .apply (settings);
@@ -631,7 +569,7 @@ LockedFlake lockFlake(
631569 if (auto resolvedPath = resolveRelativePath ()) {
632570 return readFlake (state, ref, ref, ref, *resolvedPath, inputAttrPath);
633571 } else {
634- return getFlake (state, ref, useRegistries, flakeCache, inputAttrPath);
572+ return getFlake (state, ref, useRegistries, inputAttrPath);
635573 }
636574 };
637575
@@ -779,11 +717,12 @@ LockedFlake lockFlake(
779717 if (auto resolvedPath = resolveRelativePath ()) {
780718 return {*resolvedPath, *input.ref };
781719 } else {
782- auto [accessor, resolvedRef, lockedRef] = fetchOrSubstituteTree (
783- state, *input.ref , useRegistries, flakeCache);
720+ auto cachedInput = state.inputCache ->getAccessor (state.store , input.ref ->input , useRegistries);
721+
722+ auto lockedRef = FlakeRef (std::move (cachedInput.lockedInput ), input.ref ->subdir );
784723
785724 // FIXME: allow input to be lazy.
786- auto storePath = copyInputToStore (state, lockedRef.input , input.ref ->input , accessor);
725+ auto storePath = copyInputToStore (state, lockedRef.input , input.ref ->input , cachedInput. accessor );
787726
788727 return {state.storePath (storePath), lockedRef};
789728 }
0 commit comments