libexpr: asyncify FlakeRef::fetchTree

Change-Id: I8334d8e1a9ea0e555bf2af1eb09dd9653013b28b
This commit is contained in:
eldritch horrors
2025-02-01 21:48:48 +00:00
parent d7e6721c66
commit 2da4824d61
6 changed files with 30 additions and 18 deletions
+3 -1
View File
@@ -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));
+3 -2
View File
@@ -2808,8 +2808,9 @@ std::optional<std::string> 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 {
+16 -9
View File
@@ -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<FetchedFlake> lookupInFlakeCache(
return std::nullopt;
}
static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
static kj::Promise<Result<std::tuple<fetchers::Tree, FlakeRef, FlakeRef>>> 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<fetchers::Tree, FlakeRef, FlakeRef> 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<LockedNode>(lockedRef, ref, false);
+6 -4
View File
@@ -238,10 +238,12 @@ FlakeRef FlakeRef::fromAttrs(const fetchers::Attrs & attrs)
fetchers::maybeGetStrAttr(attrs, "dir").value_or(""));
}
std::pair<fetchers::Tree, FlakeRef> FlakeRef::fetchTree(ref<Store> store) const
{
auto [tree, lockedInput] = RUN_ASYNC_IN_NEW_THREAD(input.fetch(store));
return {std::move(tree), FlakeRef(std::move(lockedInput), subdir)};
kj::Promise<Result<std::pair<fetchers::Tree, FlakeRef>>> FlakeRef::fetchTree(ref<Store> 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<FlakeRef, std::string, ExtendedOutputsSpec> parseFlakeRefWithFragmentAndExtendedOutputsSpec(
+1 -1
View File
@@ -62,7 +62,7 @@ struct FlakeRef
static FlakeRef fromAttrs(const fetchers::Attrs & attrs);
std::pair<fetchers::Tree, FlakeRef> fetchTree(ref<Store> store) const;
kj::Promise<Result<std::pair<fetchers::Tree, FlakeRef>>> fetchTree(ref<Store> store) const;
};
std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef);
+1 -1
View File
@@ -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) {