diff --git a/lix/libcmd/common-eval-args.cc b/lix/libcmd/common-eval-args.cc index 26e0380c0..b90f16c38 100644 --- a/lix/libcmd/common-eval-args.cc +++ b/lix/libcmd/common-eval-args.cc @@ -203,7 +203,9 @@ SourcePath lookupFileArg(Evaluator & state, std::string_view fileArg) experimentalFeatureSettings.require(Xp::Flakes); static constexpr size_t FLAKE_LEN = std::string_view("flake:").size(); auto flakeRef = parseFlakeRef(std::string(fileArg.substr(FLAKE_LEN)), {}, true, false); - auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first.storePath; + auto storePath = + RUN_ASYNC_IN_NEW_THREAD(flakeRef.resolve(state.store).fetchTree(state.store)) + .first.storePath; return CanonPath(state.store->toRealPath(storePath)); } else if (fileArg.size() > 2 && fileArg.at(0) == '<' && fileArg.at(fileArg.size() - 1) == '>') { Path p(fileArg.substr(1, fileArg.size() - 2)); diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index f7622cbbb..93230e39f 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -2808,8 +2808,9 @@ std::optional EvalPaths::resolveSearchPathPath(const SearchPath::Pa experimentalFeatureSettings.require(Xp::Flakes); auto flakeRef = parseFlakeRef(value.substr(6), {}, true, false); debug("fetching flake search path element '%s''", value); - auto storePath = flakeRef.resolve(store).fetchTree(store).first.storePath; - res = { store->toRealPath(storePath) }; + auto storePath = + RUN_ASYNC_IN_NEW_THREAD(flakeRef.resolve(store).fetchTree(store)).first.storePath; + res = {store->toRealPath(storePath)}; } else { diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index 33e2951bb..0de102147 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -7,6 +7,7 @@ #include "lix/libexpr/eval-inline.hh" #include "lix/libstore/store-api.hh" #include "lix/libfetchers/fetchers.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/finally.hh" #include "lix/libfetchers/fetch-settings.hh" #include "lix/libutil/terminal.hh" @@ -36,23 +37,25 @@ static std::optional lookupInFlakeCache( return std::nullopt; } -static std::tuple fetchOrSubstituteTree( +static kj::Promise>> fetchOrSubstituteTree( Evaluator & state, const FlakeRef & originalRef, bool allowLookup, FlakeCache & flakeCache) -{ +try { auto fetched = lookupInFlakeCache(flakeCache, originalRef); FlakeRef resolvedRef = originalRef; if (!fetched) { if (originalRef.input.isDirect()) { - fetched.emplace(originalRef.fetchTree(state.store)); + fetched.emplace(TRY_AWAIT(originalRef.fetchTree(state.store))); } else { if (allowLookup) { resolvedRef = originalRef.resolve(state.store); auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef); - if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store)); + if (!fetchedResolved) { + fetchedResolved.emplace(TRY_AWAIT(resolvedRef.fetchTree(state.store))); + } flakeCache.push_back({resolvedRef, *fetchedResolved}); fetched.emplace(*fetchedResolved); } @@ -72,7 +75,9 @@ static std::tuple fetchOrSubstituteTree( assert(!originalRef.input.getNarHash() || tree.storePath == originalRef.input.computeStorePath(*state.store)); - return {std::move(tree), resolvedRef, lockedRef}; + co_return {std::move(tree), resolvedRef, lockedRef}; +} catch (...) { + co_return result::current_exception(); } static void forceTrivialValue(EvalState & state, Value & value, const PosIdx pos) @@ -216,8 +221,8 @@ static Flake getFlake( FlakeCache & flakeCache, InputPath lockRootPath) { - auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state.ctx, originalRef, allowLookup, flakeCache); + auto [sourceInfo, resolvedRef, lockedRef] = + state.aio.blockOn(fetchOrSubstituteTree(state.ctx, originalRef, allowLookup, flakeCache)); // We need to guard against symlink attacks, but before we start doing // filesystem operations we should make sure there's a flake.nix in the @@ -633,8 +638,10 @@ LockedFlake lockFlake( } else { - auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state.ctx, *input.ref, useRegistries, flakeCache); + auto [sourceInfo, resolvedRef, lockedRef] = + state.aio.blockOn(fetchOrSubstituteTree( + state.ctx, *input.ref, useRegistries, flakeCache + )); auto childNode = make_ref(lockedRef, ref, false); diff --git a/lix/libexpr/flake/flakeref.cc b/lix/libexpr/flake/flakeref.cc index 663c637c8..76cffdaf4 100644 --- a/lix/libexpr/flake/flakeref.cc +++ b/lix/libexpr/flake/flakeref.cc @@ -238,10 +238,12 @@ FlakeRef FlakeRef::fromAttrs(const fetchers::Attrs & attrs) fetchers::maybeGetStrAttr(attrs, "dir").value_or("")); } -std::pair FlakeRef::fetchTree(ref store) const -{ - auto [tree, lockedInput] = RUN_ASYNC_IN_NEW_THREAD(input.fetch(store)); - return {std::move(tree), FlakeRef(std::move(lockedInput), subdir)}; +kj::Promise>> FlakeRef::fetchTree(ref store) const +try { + auto [tree, lockedInput] = TRY_AWAIT(input.fetch(store)); + co_return {std::move(tree), FlakeRef(std::move(lockedInput), subdir)}; +} catch (...) { + co_return result::current_exception(); } std::tuple parseFlakeRefWithFragmentAndExtendedOutputsSpec( diff --git a/lix/libexpr/flake/flakeref.hh b/lix/libexpr/flake/flakeref.hh index 774b85699..29beba9cd 100644 --- a/lix/libexpr/flake/flakeref.hh +++ b/lix/libexpr/flake/flakeref.hh @@ -62,7 +62,7 @@ struct FlakeRef static FlakeRef fromAttrs(const fetchers::Attrs & attrs); - std::pair fetchTree(ref store) const; + kj::Promise>> fetchTree(ref store) const; }; std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef); diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 2b45504dd..33f0659ac 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -1449,7 +1449,7 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON { auto originalRef = getFlakeRef(); auto resolvedRef = originalRef.resolve(store); - auto [tree, lockedRef] = resolvedRef.fetchTree(store); + auto [tree, lockedRef] = aio().blockOn(resolvedRef.fetchTree(store)); auto hash = store->queryPathInfo(tree.storePath)->narHash; if (json) {