1212#include " flake/settings.hh"
1313#include " value-to-json.hh"
1414#include " local-fs-store.hh"
15+ #include " fetch-to-store.hh"
1516
1617#include < nlohmann/json.hpp>
1718
@@ -24,7 +25,7 @@ namespace flake {
2425struct FetchedFlake
2526{
2627 FlakeRef lockedRef;
27- StorePath storePath ;
28+ ref<SourceAccessor> accessor ;
2829};
2930
3031typedef std::map<FlakeRef, FetchedFlake> FlakeCache;
@@ -40,7 +41,7 @@ static std::optional<FetchedFlake> lookupInFlakeCache(
4041 return i->second ;
4142}
4243
43- static std::tuple<StorePath , FlakeRef, FlakeRef> fetchOrSubstituteTree (
44+ static std::tuple<ref<SourceAccessor> , FlakeRef, FlakeRef> fetchOrSubstituteTree (
4445 EvalState & state,
4546 const FlakeRef & originalRef,
4647 bool useRegistries,
@@ -51,8 +52,8 @@ static std::tuple<StorePath, FlakeRef, FlakeRef> fetchOrSubstituteTree(
5152
5253 if (!fetched) {
5354 if (originalRef.input .isDirect ()) {
54- auto [storePath , lockedRef] = originalRef.fetchTree (state.store );
55- fetched.emplace (FetchedFlake{.lockedRef = lockedRef, .storePath = storePath });
55+ auto [accessor , lockedRef] = originalRef.lazyFetch (state.store );
56+ fetched.emplace (FetchedFlake{.lockedRef = lockedRef, .accessor = accessor });
5657 } else {
5758 if (useRegistries) {
5859 resolvedRef = originalRef.resolve (
@@ -64,8 +65,8 @@ static std::tuple<StorePath, FlakeRef, FlakeRef> fetchOrSubstituteTree(
6465 });
6566 fetched = lookupInFlakeCache (flakeCache, originalRef);
6667 if (!fetched) {
67- auto [storePath , lockedRef] = resolvedRef.fetchTree (state.store );
68- fetched.emplace (FetchedFlake{.lockedRef = lockedRef, .storePath = storePath });
68+ auto [accessor , lockedRef] = resolvedRef.lazyFetch (state.store );
69+ fetched.emplace (FetchedFlake{.lockedRef = lockedRef, .accessor = accessor });
6970 }
7071 flakeCache.insert_or_assign (resolvedRef, *fetched);
7172 }
@@ -76,14 +77,28 @@ static std::tuple<StorePath, FlakeRef, FlakeRef> fetchOrSubstituteTree(
7677 flakeCache.insert_or_assign (originalRef, *fetched);
7778 }
7879
79- debug (" got tree '%s' from '%s'" ,
80- state.store ->printStorePath (fetched->storePath ), fetched->lockedRef );
80+ debug (" got tree '%s' from '%s'" , fetched->accessor , fetched->lockedRef );
8181
82- state.allowPath (fetched->storePath );
82+ return {fetched->accessor , resolvedRef, fetched->lockedRef };
83+ }
84+
85+ static StorePath copyInputToStore (
86+ EvalState & state,
87+ fetchers::Input & input,
88+ ref<SourceAccessor> accessor)
89+ {
90+ auto storePath = fetchToStore (*state.store , accessor, FetchMode::Copy, input.getName ());
91+
92+ state.allowPath (storePath);
8393
94+ auto narHash = state.store ->queryPathInfo (storePath)->narHash ;
95+ input.attrs .insert_or_assign (" narHash" , narHash.to_string (HashFormat::SRI, true ));
96+
97+ #if 0
8498 assert(!originalRef.input.getNarHash() || fetched->storePath == originalRef.input.computeStorePath(*state.store));
99+ #endif
85100
86- return {fetched-> storePath , resolvedRef, fetched-> lockedRef } ;
101+ return storePath;
87102}
88103
89104static void forceTrivialValue (EvalState & state, Value & value, const PosIdx pos)
@@ -136,7 +151,9 @@ static FlakeInput parseFlakeInput(
136151 url = attr.value ->string_view ();
137152 else if (attr.value ->type () == nPath) {
138153 auto path = attr.value ->path ();
139- if (path.accessor != flakeDir.accessor )
154+ if (path.accessor != flakeDir.accessor
155+ // FIXME: hack necessary since the parser currently stores all paths as inside rootFS.
156+ && flakeDir.accessor == state.rootFS )
140157 throw Error (" input attribute path '%s' at %s must be in the same source tree as %s" ,
141158 path, state.positions [attr.pos ], flakeDir);
142159 url = " path:" + flakeDir.path .makeRelative (path.path );
@@ -301,10 +318,12 @@ static Flake readFlake(
301318 state.symbols [setting.name ],
302319 std::string (state.forceStringNoCtx (*setting.value , setting.pos , " " )));
303320 else if (setting.value ->type () == nPath) {
304- NixStringContext emptyContext = {};
321+ // FIXME: hack necessary since the parser currently stores all paths as inside rootFS.
322+ SourcePath path (rootDir.accessor , setting.value ->path ().path );
323+ auto storePath = fetchToStore (*state.store , path, FetchMode::Copy);
305324 flake.config .settings .emplace (
306325 state.symbols [setting.name ],
307- state.coerceToString (setting. pos , *setting. value , emptyContext, " " , false , true , true ). toOwned ( ));
326+ state.store -> toRealPath (storePath ));
308327 }
309328 else if (setting.value ->type () == nInt)
310329 flake.config .settings .emplace (
@@ -349,9 +368,14 @@ static Flake getFlake(
349368 FlakeCache & flakeCache,
350369 const InputAttrPath & lockRootAttrPath)
351370{
352- auto [storePath, resolvedRef, lockedRef] = fetchOrSubstituteTree (
371+ // Fetch a lazy tree first.
372+ auto [accessor, resolvedRef, lockedRef] = fetchOrSubstituteTree (
353373 state, originalRef, useRegistries, flakeCache);
354374
375+ // Copy the tree to the store.
376+ auto storePath = copyInputToStore (state, lockedRef.input , accessor);
377+
378+ // Re-parse flake.nix from the store.
355379 return readFlake (state, originalRef, resolvedRef, lockedRef, state.rootPath (state.store ->toRealPath (storePath)), lockRootAttrPath);
356380}
357381
@@ -707,8 +731,12 @@ LockedFlake lockFlake(
707731 if (auto resolvedPath = resolveRelativePath ()) {
708732 return {*resolvedPath, *input.ref };
709733 } else {
710- auto [storePath , resolvedRef, lockedRef] = fetchOrSubstituteTree (
734+ auto [accessor , resolvedRef, lockedRef] = fetchOrSubstituteTree (
711735 state, *input.ref , useRegistries, flakeCache);
736+
737+ // FIXME: allow input to be lazy.
738+ auto storePath = copyInputToStore (state, lockedRef.input , accessor);
739+
712740 return {state.rootPath (state.store ->toRealPath (storePath)), lockedRef};
713741 }
714742 }();
0 commit comments