diff --git a/lix/legacy/dotgraph.cc b/lix/legacy/dotgraph.cc index eec1f0a3a..cd7e8e75e 100644 --- a/lix/legacy/dotgraph.cc +++ b/lix/legacy/dotgraph.cc @@ -1,5 +1,6 @@ #include "dotgraph.hh" #include "lix/libstore/store-api.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/result.hh" #include @@ -56,7 +57,7 @@ try { cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000"); - for (auto & p : store->queryPathInfo(path)->references) { + for (auto & p : TRY_AWAIT(store->queryPathInfo(path))->references) { if (p != path) { workList.insert(p); cout << makeEdge(std::string(p.to_string()), std::string(path.to_string())); diff --git a/lix/legacy/graphml.cc b/lix/legacy/graphml.cc index 5cb4f6bc0..b70aabf77 100644 --- a/lix/legacy/graphml.cc +++ b/lix/legacy/graphml.cc @@ -1,6 +1,7 @@ #include "graphml.hh" #include "lix/libstore/store-api.hh" #include "lix/libstore/derivations.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/result.hh" #include @@ -68,7 +69,7 @@ try { ret = doneSet.insert(path); if (ret.second == false) continue; - auto info = store->queryPathInfo(path); + auto info = TRY_AWAIT(store->queryPathInfo(path)); cout << makeNode(*info); for (auto & p : info->references) { diff --git a/lix/legacy/nix-store.cc b/lix/legacy/nix-store.cc index 9eb29611e..7d6b8c181 100644 --- a/lix/legacy/nix-store.cc +++ b/lix/legacy/nix-store.cc @@ -51,13 +51,15 @@ ref ensureLocalStore() } -static StorePath useDeriver(const StorePath & path) -{ - if (path.isDerivation()) return path; - auto info = store->queryPathInfo(path); +static kj::Promise> useDeriver(const StorePath & path) +try { + if (path.isDerivation()) co_return path; + auto info = TRY_AWAIT(store->queryPathInfo(path)); if (!info->deriver) throw Error("deriver of path '%s' is not known", store->printStorePath(path)); - return *info->deriver; + co_return *info->deriver; +} catch (...) { + co_return result::current_exception(); } @@ -278,7 +280,7 @@ static void printTree(AsyncIoRoot & aio, const StorePath & path, cout << fmt("%s%s\n", firstPad, store->printStorePath(path)); - auto info = store->queryPathInfo(path); + auto info = aio.blockOn(store->queryPathInfo(path)); /* Topologically sort under the relation A < B iff A \in closure(B). That is, if derivation A is an (possibly indirect) @@ -368,7 +370,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) aio.blockOn(store->computeFSClosure(j, paths, false, includeOutputs)); } else if (query == qReferences) { - for (auto & p : store->queryPathInfo(j)->references) + for (auto & p : aio.blockOn(store->queryPathInfo(j))->references) paths.insert(p); } else if (query == qReferrers) { @@ -390,7 +392,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) case qDeriver: for (auto & i : opArgs) { - auto info = store->queryPathInfo(store->followLinksToStorePath(i)); + auto info = aio.blockOn(store->queryPathInfo(store->followLinksToStorePath(i))); cout << fmt("%s\n", info->deriver ? store->printStorePath(*info->deriver) : "unknown-deriver"); } break; @@ -413,7 +415,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) case qBinding: for (auto & i : opArgs) { - auto path = useDeriver(store->followLinksToStorePath(i)); + auto path = aio.blockOn(useDeriver(store->followLinksToStorePath(i))); Derivation drv = aio.blockOn(store->derivationFromPath(path)); StringPairs::iterator j = drv.env.find(bindingName); if (j == drv.env.end()) @@ -427,7 +429,7 @@ static void opQuery(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) case qSize: for (auto & i : opArgs) { for (auto & j : aio.blockOn(maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise))) { - auto info = store->queryPathInfo(j); + auto info = aio.blockOn(store->queryPathInfo(j)); if (query == qHash) { assert(info->narHash.type == HashType::SHA256); cout << fmt("%s\n", info->narHash.to_string(Base::Base32, true)); @@ -789,7 +791,7 @@ static void opVerifyPath(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) for (auto & i : opArgs) { auto path = store->followLinksToStorePath(i); printMsg(lvlTalkative, "checking path '%s'...", store->printStorePath(path)); - auto info = store->queryPathInfo(path); + auto info = aio.blockOn(store->queryPathInfo(path)); HashSink sink(info->narHash.type); aio.blockOn(store->narFromPath(path))->drainInto(sink); auto current = sink.finish(); @@ -917,7 +919,7 @@ static void opServe(AsyncIoRoot & aio, Strings opFlags, Strings opArgs) // !!! Maybe we want a queryPathInfos? for (auto & i : paths) { try { - auto info = store->queryPathInfo(i); + auto info = aio.blockOn(store->queryPathInfo(i)); out << store->printStorePath(info->path); out << ServeProto::write(*store, wconn, static_cast(*info)); } catch (InvalidPath &) { diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index e1a9be9ce..e918a6058 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -1284,7 +1284,11 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V StorePathSet refs; if (state.ctx.store->isInStore(path.canonical().abs())) { try { - refs = state.ctx.store->queryPathInfo(state.ctx.store->toStorePath(path.canonical().abs()).first)->references; + refs = state.aio + .blockOn(state.ctx.store->queryPathInfo( + state.ctx.store->toStorePath(path.canonical().abs()).first + )) + ->references; } catch (Error &) { // FIXME: should be InvalidPathError } // Re-scan references to filter down to just the ones that actually occur in the file. @@ -1530,7 +1534,7 @@ static void addPath( try { auto [storePath, subPath] = state.ctx.store->toStorePath(path); // FIXME: we should scanForReferences on the path before adding it - refs = state.ctx.store->queryPathInfo(storePath)->references; + refs = state.aio.blockOn(state.ctx.store->queryPathInfo(storePath))->references; realPath = state.ctx.store->toRealPath(path); } catch (Error &) { // FIXME: should be InvalidPathError } diff --git a/lix/libexpr/primops/fetchClosure.cc b/lix/libexpr/primops/fetchClosure.cc index 9912f8bc7..07083e646 100644 --- a/lix/libexpr/primops/fetchClosure.cc +++ b/lix/libexpr/primops/fetchClosure.cc @@ -46,7 +46,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor // check and return - auto resultInfo = state.ctx.store->queryPathInfo(toPath); + auto resultInfo = state.aio.blockOn(state.ctx.store->queryPathInfo(toPath)); if (!resultInfo->isContentAddressed(*state.ctx.store)) { // We don't perform the rewriting when outPath already exists, as an optimisation. @@ -71,7 +71,7 @@ static void runFetchClosureWithContentAddressedPath(EvalState & state, const Pos if (!state.aio.blockOn(state.ctx.store->isValidPath(fromPath))) state.aio.blockOn(copyClosure(fromStore, *state.ctx.store, RealisedPath::Set { fromPath })); - auto info = state.ctx.store->queryPathInfo(fromPath); + auto info = state.aio.blockOn(state.ctx.store->queryPathInfo(fromPath)); if (!info->isContentAddressed(*state.ctx.store)) { throw Error({ @@ -97,7 +97,7 @@ static void runFetchClosureWithInputAddressedPath(EvalState & state, const PosId if (!state.aio.blockOn(state.ctx.store->isValidPath(fromPath))) state.aio.blockOn(copyClosure(fromStore, *state.ctx.store, RealisedPath::Set { fromPath })); - auto info = state.ctx.store->queryPathInfo(fromPath); + auto info = state.aio.blockOn(state.ctx.store->queryPathInfo(fromPath)); if (info->isContentAddressed(*state.ctx.store)) { throw Error({ diff --git a/lix/libexpr/primops/fetchTree.cc b/lix/libexpr/primops/fetchTree.cc index 037137dbe..83a79c673 100644 --- a/lix/libexpr/primops/fetchTree.cc +++ b/lix/libexpr/primops/fetchTree.cc @@ -280,7 +280,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v if (expectedHash) { auto hash = unpack - ? state.ctx.store->queryPathInfo(storePath)->narHash + ? state.aio.blockOn(state.ctx.store->queryPathInfo(storePath))->narHash : hashFile(HashType::SHA256, state.ctx.store->toRealPath(storePath)); if (hash != *expectedHash) { state.ctx.errors.make( diff --git a/lix/libfetchers/fetchers.cc b/lix/libfetchers/fetchers.cc index dcd8a8080..51e5d7b2b 100644 --- a/lix/libfetchers/fetchers.cc +++ b/lix/libfetchers/fetchers.cc @@ -176,7 +176,7 @@ try { .storePath = storePath, }; - auto narHash = store->queryPathInfo(tree.storePath)->narHash; + auto narHash = TRY_AWAIT(store->queryPathInfo(tree.storePath))->narHash; input.attrs.insert_or_assign("narHash", narHash.to_string(Base::SRI, true)); if (auto prevNarHash = getNarHash()) { diff --git a/lix/libstore/binary-cache-store.cc b/lix/libstore/binary-cache-store.cc index e027c092c..eeb3bc08d 100644 --- a/lix/libstore/binary-cache-store.cc +++ b/lix/libstore/binary-cache-store.cc @@ -166,7 +166,7 @@ try { for (auto & ref : info.references) try { if (ref != info.path) - queryPathInfo(ref); + TRY_AWAIT(queryPathInfo(ref)); } catch (InvalidPath &) { throw Error("cannot add '%s' to the binary cache because the reference '%s' does not exist", printStorePath(info.path), printStorePath(ref)); @@ -343,7 +343,7 @@ BinaryCacheStore::queryPathFromHashPart(const std::string & hashPart) try { auto pseudoPath = StorePath(hashPart + "-" + MissingName); try { - auto info = queryPathInfo(pseudoPath); + auto info = TRY_AWAIT(queryPathInfo(pseudoPath)); co_return info->path; } catch (InvalidPath &) { co_return std::nullopt; @@ -354,7 +354,7 @@ try { kj::Promise>> BinaryCacheStore::narFromPath(const StorePath & storePath) try { - auto info = queryPathInfo(storePath).cast(); + auto info = TRY_AWAIT(queryPathInfo(storePath)).cast(); try { auto file = getFile(info->url); @@ -385,8 +385,9 @@ try { co_return result::current_exception(); } -std::shared_ptr BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath) -{ +kj::Promise>> +BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath) +try { auto uri = getUri(); auto storePathS = printStorePath(storePath); auto act = std::make_shared(*logger, lvlTalkative, actQueryPathInfo, @@ -397,11 +398,13 @@ std::shared_ptr BinaryCacheStore::queryPathInfoUncached(con auto data = getFileContents(narInfoFile); - if (!data) return nullptr; + if (!data) co_return result::success(nullptr); stats.narInfoRead++; - return std::make_shared(*this, *data, narInfoFile); + co_return std::make_shared(*this, *data, narInfoFile); +} catch (...) { + co_return result::current_exception(); } static ValidPathInfo makeAddToStoreInfo( @@ -542,7 +545,8 @@ try { S3 might return an outdated cached version. */ // downcast: BinaryCacheStore always returns NarInfo from queryPathInfoUncached, making it sound - auto narInfo = make_ref(dynamic_cast(*queryPathInfo(storePath))); + auto narInfo = + make_ref(dynamic_cast(*TRY_AWAIT(queryPathInfo(storePath)))); narInfo->sigs.insert(sigs.begin(), sigs.end()); diff --git a/lix/libstore/binary-cache-store.hh b/lix/libstore/binary-cache-store.hh index 18399255f..cea019891 100644 --- a/lix/libstore/binary-cache-store.hh +++ b/lix/libstore/binary-cache-store.hh @@ -111,7 +111,8 @@ public: kj::Promise> isValidPathUncached(const StorePath & path) override; - std::shared_ptr queryPathInfoUncached(const StorePath & path) override; + kj::Promise>> + queryPathInfoUncached(const StorePath & path) override; kj::Promise>> queryPathFromHashPart(const std::string & hashPart) override; diff --git a/lix/libstore/build/entry-points.cc b/lix/libstore/build/entry-points.cc index b2a29c0cb..98e8e533b 100644 --- a/lix/libstore/build/entry-points.cc +++ b/lix/libstore/build/entry-points.cc @@ -145,7 +145,7 @@ try { if (result.exitCode != Goal::ecSuccess) { /* Since substituting the path didn't work, if we have a valid deriver, then rebuild the deriver. */ - auto info = queryPathInfo(path); + auto info = TRY_AWAIT(queryPathInfo(path)); if (info->deriver && TRY_AWAIT(isValidPath(*info->deriver))) { TRY_AWAIT(processGoals(*this, *this, [&](GoalFactory & gf) { Worker::Targets goals; diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index c19287c23..ab066790b 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -1050,23 +1050,26 @@ struct RestrictedStore : public virtual IndirectRootStore, public virtual GcStor co_return result::current_exception(); } - std::shared_ptr queryPathInfoUncached(const StorePath & path) override - { + kj::Promise>> + queryPathInfoUncached(const StorePath & path) override + try { if (goal.isAllowed(path)) { try { /* Censor impure information. */ - auto info = std::make_shared(*next->queryPathInfo(path)); + auto info = std::make_shared(*TRY_AWAIT(next->queryPathInfo(path))); info->deriver.reset(); info->registrationTime = 0; info->ultimate = false; info->sigs.clear(); - return info; + co_return info; } catch (InvalidPath &) { - return nullptr; + co_return result::success(nullptr); } } else - return nullptr; - }; + co_return result::success(nullptr); + } catch (...) { + co_return result::current_exception(); + } kj::Promise> queryReferrers(const StorePath & path, StorePathSet & referrers) override @@ -2403,7 +2406,7 @@ try { if (buildMode == bmCheck) { if (!TRY_AWAIT(worker.store.isValidPath(newInfo.path))) continue; - ValidPathInfo oldInfo(*worker.store.queryPathInfo(newInfo.path)); + ValidPathInfo oldInfo(*TRY_AWAIT(worker.store.queryPathInfo(newInfo.path))); if (newInfo.narHash != oldInfo.narHash) { anyCheckMismatchSeen = true; if (settings.runDiffHook || settings.keepFailed) { @@ -2558,115 +2561,132 @@ try { /* Compute the closure and closure size of some output. This is slightly tricky because some of its references (namely other outputs) may not be valid yet. */ - auto getClosure = [&](const StorePath & path) - { - uint64_t closureSize = 0; - StorePathSet pathsDone; - std::queue pathsLeft; - pathsLeft.push(path); + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + auto getClosure = [&](const StorePath & path + ) -> kj::Promise>> { + try { + uint64_t closureSize = 0; + StorePathSet pathsDone; + std::queue pathsLeft; + pathsLeft.push(path); - while (!pathsLeft.empty()) { - auto path = pathsLeft.front(); - pathsLeft.pop(); - if (!pathsDone.insert(path).second) continue; + while (!pathsLeft.empty()) { + auto path = pathsLeft.front(); + pathsLeft.pop(); + if (!pathsDone.insert(path).second) continue; - auto i = outputsByPath.find(worker.store.printStorePath(path)); - if (i != outputsByPath.end()) { - closureSize += i->second.narSize; - for (auto & ref : i->second.references) - pathsLeft.push(ref); - } else { - auto info = worker.store.queryPathInfo(path); - closureSize += info->narSize; - for (auto & ref : info->references) - pathsLeft.push(ref); + auto i = outputsByPath.find(worker.store.printStorePath(path)); + if (i != outputsByPath.end()) { + closureSize += i->second.narSize; + for (auto & ref : i->second.references) + pathsLeft.push(ref); + } else { + auto info = TRY_AWAIT(worker.store.queryPathInfo(path)); + closureSize += info->narSize; + for (auto & ref : info->references) + pathsLeft.push(ref); + } } - } - return std::make_pair(std::move(pathsDone), closureSize); + co_return std::make_pair(std::move(pathsDone), closureSize); + } catch (...) { + co_return result::current_exception(); + } }; - auto applyChecks = [&](const Checks & checks) - { - if (checks.maxSize && info.narSize > *checks.maxSize) - throw BuildError("path '%s' is too large at %d bytes; limit is %d bytes", - worker.store.printStorePath(info.path), info.narSize, *checks.maxSize); + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + auto applyChecks = [&](const Checks & checks) -> kj::Promise> { + try { + if (checks.maxSize && info.narSize > *checks.maxSize) + throw BuildError("path '%s' is too large at %d bytes; limit is %d bytes", + worker.store.printStorePath(info.path), info.narSize, *checks.maxSize); - if (checks.maxClosureSize) { - uint64_t closureSize = getClosure(info.path).second; - if (closureSize > *checks.maxClosureSize) - throw BuildError("closure of path '%s' is too large at %d bytes; limit is %d bytes", - worker.store.printStorePath(info.path), closureSize, *checks.maxClosureSize); - } + if (checks.maxClosureSize) { + uint64_t closureSize = TRY_AWAIT(getClosure(info.path)).second; + if (closureSize > *checks.maxClosureSize) + throw BuildError("closure of path '%s' is too large at %d bytes; limit is %d bytes", + worker.store.printStorePath(info.path), closureSize, *checks.maxClosureSize); + } - auto checkRefs = [&](const std::optional & value, bool allowed, bool recursive) - { - if (!value) return; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + auto checkRefs = [&](const std::optional & value, + bool allowed, + bool recursive) -> kj::Promise> { + try { + if (!value) co_return result::success(); - /* Parse a list of reference specifiers. Each element must - either be a store path, or the symbolic name of the output - of the derivation (such as `out'). */ - StorePathSet spec; - for (auto & i : *value) { - if (worker.store.isStorePath(i)) - spec.insert(worker.store.parseStorePath(i)); - else if (auto output = get(newlyBuiltOutputs, i)) - spec.insert(output->path); - else if (auto storePath = get(alreadyRegisteredOutputs, i)) - spec.insert(*storePath); - else { - std::string outputsListing = concatMapStringsSep( - ", ", - newlyBuiltOutputs, - [](auto & o) { return o.first; } - ); - if (!alreadyRegisteredOutputs.empty()) { - outputsListing.append(outputsListing.empty() ? "" : ", "); - outputsListing.append(concatMapStringsSep( - ", ", - alreadyRegisteredOutputs, - [](auto & o) { return o.first; }) - ); + /* Parse a list of reference specifiers. Each element must + either be a store path, or the symbolic name of the output + of the derivation (such as `out'). */ + StorePathSet spec; + for (auto & i : *value) { + if (worker.store.isStorePath(i)) + spec.insert(worker.store.parseStorePath(i)); + else if (auto output = get(newlyBuiltOutputs, i)) + spec.insert(output->path); + else if (auto storePath = get(alreadyRegisteredOutputs, i)) + spec.insert(*storePath); + else { + std::string outputsListing = concatMapStringsSep( + ", ", + newlyBuiltOutputs, + [](auto & o) { return o.first; } + ); + if (!alreadyRegisteredOutputs.empty()) { + outputsListing.append(outputsListing.empty() ? "" : ", "); + outputsListing.append(concatMapStringsSep( + ", ", + alreadyRegisteredOutputs, + [](auto & o) { return o.first; }) + ); + } + throw BuildError("derivation '%s' output check for '%s' contains an illegal reference specifier '%s'," + " expected store path or output name (one of [%s])", + worker.store.printStorePath(drvPath), outputName, i, outputsListing); + } } - throw BuildError("derivation '%s' output check for '%s' contains an illegal reference specifier '%s'," - " expected store path or output name (one of [%s])", - worker.store.printStorePath(drvPath), outputName, i, outputsListing); + + auto used = recursive + ? TRY_AWAIT(getClosure(info.path)).first + : info.references; + + if (recursive && checks.ignoreSelfRefs) + used.erase(info.path); + + StorePathSet badPaths; + + for (auto & i : used) + if (allowed) { + if (!spec.count(i)) + badPaths.insert(i); + } else { + if (spec.count(i)) + badPaths.insert(i); + } + + if (!badPaths.empty()) { + std::string badPathsStr; + for (auto & i : badPaths) { + badPathsStr += "\n "; + badPathsStr += worker.store.printStorePath(i); + } + throw BuildError("output '%s' is not allowed to refer to the following paths:%s", + worker.store.printStorePath(info.path), badPathsStr); + } + co_return result::success(); + } catch (...) { + co_return result::current_exception(); } - } + }; - auto used = recursive - ? getClosure(info.path).first - : info.references; - - if (recursive && checks.ignoreSelfRefs) - used.erase(info.path); - - StorePathSet badPaths; - - for (auto & i : used) - if (allowed) { - if (!spec.count(i)) - badPaths.insert(i); - } else { - if (spec.count(i)) - badPaths.insert(i); - } - - if (!badPaths.empty()) { - std::string badPathsStr; - for (auto & i : badPaths) { - badPathsStr += "\n "; - badPathsStr += worker.store.printStorePath(i); - } - throw BuildError("output '%s' is not allowed to refer to the following paths:%s", - worker.store.printStorePath(info.path), badPathsStr); - } - }; - - checkRefs(checks.allowedReferences, true, false); - checkRefs(checks.allowedRequisites, true, true); - checkRefs(checks.disallowedReferences, false, false); - checkRefs(checks.disallowedRequisites, false, true); + TRY_AWAIT(checkRefs(checks.allowedReferences, true, false)); + TRY_AWAIT(checkRefs(checks.allowedRequisites, true, true)); + TRY_AWAIT(checkRefs(checks.disallowedReferences, false, false)); + TRY_AWAIT(checkRefs(checks.disallowedRequisites, false, true)); + co_return result::success(); + } catch (...) { + co_return result::current_exception(); + } }; if (auto structuredAttrs = parsedDrv->getStructuredAttrs()) { @@ -2717,7 +2737,7 @@ try { checks.disallowedReferences = get_("disallowedReferences"); checks.disallowedRequisites = get_("disallowedRequisites"); - applyChecks(checks); + TRY_AWAIT(applyChecks(checks)); } } } else { @@ -2728,7 +2748,7 @@ try { checks.allowedRequisites = parsedDrv->getStringsAttr("allowedRequisites"); checks.disallowedReferences = parsedDrv->getStringsAttr("disallowedReferences"); checks.disallowedRequisites = parsedDrv->getStringsAttr("disallowedRequisites"); - applyChecks(checks); + TRY_AWAIT(applyChecks(checks)); } } diff --git a/lix/libstore/build/substitution-goal.cc b/lix/libstore/build/substitution-goal.cc index d4c4acfef..ca043738a 100644 --- a/lix/libstore/build/substitution-goal.cc +++ b/lix/libstore/build/substitution-goal.cc @@ -109,8 +109,7 @@ try { do { try { - // FIXME: make async - info = sub->queryPathInfo(subPath ? *subPath : storePath); + info = TRY_AWAIT(sub->queryPathInfo(subPath ? *subPath : storePath)); break; } catch (InvalidPath &) { } catch (SubstituterDisabled &) { diff --git a/lix/libstore/build/worker.cc b/lix/libstore/build/worker.cc index 2e23ab0ba..2523d2802 100644 --- a/lix/libstore/build/worker.cc +++ b/lix/libstore/build/worker.cc @@ -1,5 +1,6 @@ #include "build/derivation-goal.hh" #include "lix/libutil/async-collect.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/charptr-cast.hh" #include "lix/libstore/build/worker.hh" #include "lix/libutil/finally.hh" @@ -326,7 +327,7 @@ try { auto i = pathContentsGoodCache.find(path); if (i != pathContentsGoodCache.end()) co_return i->second; printInfo("checking path '%s'...", store.printStorePath(path)); - auto info = store.queryPathInfo(path); + auto info = TRY_AWAIT(store.queryPathInfo(path)); bool res; if (!pathExists(store.printStorePath(path))) res = false; diff --git a/lix/libstore/daemon.cc b/lix/libstore/daemon.cc index 055feeb0b..7345ddb72 100644 --- a/lix/libstore/daemon.cc +++ b/lix/libstore/daemon.cc @@ -426,14 +426,14 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref store // We could stream this by changing Store std::string contents = source.drain(); auto path = aio.blockOn(store->addTextToStore(name, contents, refs, repair)); - return store->queryPathInfo(path); + return aio.blockOn(store->queryPathInfo(path)); }, [&](const FileIngestionMethod & fim) { AsyncSourceInputStream stream{source}; auto path = aio.blockOn( store->addToStoreFromDump(stream, name, fim, hashType, repair, refs) ); - return store->queryPathInfo(path); + return aio.blockOn(store->queryPathInfo(path)); }, }, contentAddressMethod.raw); }(); @@ -837,7 +837,7 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref store std::shared_ptr info; logger->startWork(); try { - info = store->queryPathInfo(path); + info = aio.blockOn(store->queryPathInfo(path)); } catch (InvalidPath &) { // The path being invalid isn't fatal here since it will just be // sent as not present. diff --git a/lix/libstore/dummy-store.cc b/lix/libstore/dummy-store.cc index aa2f11d5a..ea8d0d33a 100644 --- a/lix/libstore/dummy-store.cc +++ b/lix/libstore/dummy-store.cc @@ -34,9 +34,10 @@ struct DummyStore final : public Store return *uriSchemes().begin(); } - std::shared_ptr queryPathInfoUncached(const StorePath & path) override + kj::Promise>> + queryPathInfoUncached(const StorePath & path) override { - return nullptr; + return {result::success(nullptr)}; } /** diff --git a/lix/libstore/export-import.cc b/lix/libstore/export-import.cc index 356073e84..a17ce2af2 100644 --- a/lix/libstore/export-import.cc +++ b/lix/libstore/export-import.cc @@ -27,7 +27,7 @@ try { kj::Promise> Store::exportPath(const StorePath & path, Sink & sink) try { - auto info = queryPathInfo(path); + auto info = TRY_AWAIT(queryPathInfo(path)); HashSink hashSink(HashType::SHA256); TeeSink teeSink(sink, hashSink); diff --git a/lix/libstore/gc.cc b/lix/libstore/gc.cc index de9542aac..b5a7ffc4c 100644 --- a/lix/libstore/gc.cc +++ b/lix/libstore/gc.cc @@ -780,7 +780,7 @@ try { { if (maybeOutPath && TRY_AWAIT(isValidPath(*maybeOutPath)) && - queryPathInfo(*maybeOutPath)->deriver == *path) + TRY_AWAIT(queryPathInfo(*maybeOutPath))->deriver == *path) enqueue(*maybeOutPath); } } diff --git a/lix/libstore/legacy-ssh-store.cc b/lix/libstore/legacy-ssh-store.cc index ffb727f7d..64bcea3b1 100644 --- a/lix/libstore/legacy-ssh-store.cc +++ b/lix/libstore/legacy-ssh-store.cc @@ -160,8 +160,9 @@ struct LegacySSHStore final : public Store return *uriSchemes().begin() + "://" + host; } - std::shared_ptr queryPathInfoUncached(const StorePath & path) override - { + kj::Promise>> + queryPathInfoUncached(const StorePath & path) override + try { auto conn(connections->get()); /* No longer support missing NAR hash */ @@ -173,7 +174,7 @@ struct LegacySSHStore final : public Store conn->to.flush(); auto p = readString(conn->from); - if (p.empty()) return nullptr; + if (p.empty()) co_return result::success(nullptr); auto path2 = parseStorePath(p); assert(path == path2); auto info = std::make_shared( @@ -186,7 +187,9 @@ struct LegacySSHStore final : public Store auto s = readString(conn->from); assert(s == ""); - return info; + co_return info; + } catch (...) { + co_return result::current_exception(); } kj::Promise> addToStore(const ValidPathInfo & info, AsyncInputStream & source, diff --git a/lix/libstore/local-store.cc b/lix/libstore/local-store.cc index 03e1ec81b..b0c6edaab 100644 --- a/lix/libstore/local-store.cc +++ b/lix/libstore/local-store.cc @@ -916,12 +916,22 @@ try { } -std::shared_ptr LocalStore::queryPathInfoUncached(const StorePath & path) -{ - return retrySQLite([&]() { - auto state = dbPool.get(); - return queryPathInfoInternal(*state, path); - }, always_progresses); +kj::Promise>> +LocalStore::queryPathInfoUncached(const StorePath & path) +try { + co_return TRY_AWAIT( + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + retrySQLite([&]() -> kj::Promise>> { + try { + auto state = dbPool.get(); + co_return queryPathInfoInternal(*state, path); + } catch (...) { + co_return result::current_exception(); + } + }) + ); +} catch (...) { + co_return result::current_exception(); } @@ -1734,7 +1744,9 @@ try { for (auto & i : validPaths) { std::optional caught; try { - auto info = std::const_pointer_cast(std::shared_ptr(queryPathInfo(i))); + auto info = std::const_pointer_cast( + std::shared_ptr(TRY_AWAIT(queryPathInfo(i))) + ); /* Check the content hash (optionally - slow). */ printMsg(lvlTalkative, "checking contents of '%s'", printStorePath(i)); diff --git a/lix/libstore/local-store.hh b/lix/libstore/local-store.hh index aa0b41ed7..968e8eb48 100644 --- a/lix/libstore/local-store.hh +++ b/lix/libstore/local-store.hh @@ -196,7 +196,8 @@ public: kj::Promise> queryAllValidPaths() override; - std::shared_ptr queryPathInfoUncached(const StorePath & path) override; + kj::Promise>> + queryPathInfoUncached(const StorePath & path) override; kj::Promise> queryReferrers(const StorePath & path, StorePathSet & referrers) override; diff --git a/lix/libstore/make-content-addressed.cc b/lix/libstore/make-content-addressed.cc index 7a41f538a..ccfa05d88 100644 --- a/lix/libstore/make-content-addressed.cc +++ b/lix/libstore/make-content-addressed.cc @@ -22,7 +22,7 @@ try { for (auto & path : paths) { auto pathS = srcStore.printStorePath(path); - auto oldInfo = srcStore.queryPathInfo(path); + auto oldInfo = TRY_AWAIT(srcStore.queryPathInfo(path)); std::string oldHashPart(path.hashPart()); StringSink sink; diff --git a/lix/libstore/misc.cc b/lix/libstore/misc.cc index ddb558b72..33d7ec459 100644 --- a/lix/libstore/misc.cc +++ b/lix/libstore/misc.cc @@ -9,6 +9,7 @@ #include "lix/libutil/closure.hh" #include "lix/libstore/filetransfer.hh" #include "lix/libutil/strings.hh" +#include #include namespace nix { @@ -70,8 +71,13 @@ try { paths_.merge(TRY_AWAIT(computeClosureAsync( startPaths, - [&](const StorePath& path) -> kj::Promise>> { - return queryDeps(path, queryPathInfo(path)); + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + [&](const StorePath& path) -> kj::Promise> { + try { + co_return TRY_AWAIT(queryDeps(path, TRY_AWAIT(queryPathInfo(path)))); + } catch (...) { + co_return result::current_exception(); + } }))); co_return result::success(); } catch (...) { @@ -369,12 +375,15 @@ try { kj::Promise> Store::topoSortPaths(const StorePathSet & paths) try { - co_return topoSort(paths, - {[&](const StorePath & path) { + co_return TRY_AWAIT(topoSortAsync(paths, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + {[&](const StorePath & path) -> kj::Promise> { try { - return queryPathInfo(path)->references; + co_return TRY_AWAIT(queryPathInfo(path))->references; } catch (InvalidPath &) { - return StorePathSet(); + co_return StorePathSet(); + } catch (...) { + co_return result::current_exception(); } }}, {[&](const StorePath & path, const StorePath & parent) { @@ -382,7 +391,7 @@ try { "cycle detected in the references of '%s' from '%s'", printStorePath(path), printStorePath(parent)); - }}); + }})); } catch (...) { co_return result::current_exception(); } @@ -461,7 +470,7 @@ try { for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map) TRY_AWAIT(accumRealisations(inputDrv, inputNode)); - auto info = store.queryPathInfo(outputPath); + auto info = TRY_AWAIT(store.queryPathInfo(outputPath)); co_return TRY_AWAIT(drvOutputReferences( TRY_AWAIT(Realisation::closure(store, inputRealisations)), info->references diff --git a/lix/libstore/remote-store.cc b/lix/libstore/remote-store.cc index 7e1597963..38ddedd47 100644 --- a/lix/libstore/remote-store.cc +++ b/lix/libstore/remote-store.cc @@ -286,8 +286,9 @@ try { } -std::shared_ptr RemoteStore::queryPathInfoUncached(const StorePath & path) -{ +kj::Promise>> +RemoteStore::queryPathInfoUncached(const StorePath & path) +try { auto conn(getConnection()); conn->to << WorkerProto::Op::QueryPathInfo << printStorePath(path); try { @@ -295,16 +296,18 @@ std::shared_ptr RemoteStore::queryPathInfoUncached(const St } catch (Error & e) { // Ugly backwards compatibility hack. TODO(fj#325): remove. if (e.msg().find("is not valid") != std::string::npos) - return nullptr; + co_return result::success(nullptr); throw; } bool valid; conn->from >> valid; - if (!valid) return nullptr; + if (!valid) co_return result::success(nullptr); - return std::make_shared( + co_return std::make_shared( StorePath{path}, WorkerProto::Serialise::read(*this, *conn)); +} catch (...) { + co_return result::current_exception(); } @@ -497,7 +500,7 @@ try { auto path = parseStorePath(readString(conn->from)); // Release our connection to prevent a deadlock in queryPathInfo(). conn_.reset(); - co_return queryPathInfo(path); + co_return TRY_AWAIT(queryPathInfo(path)); } } catch (...) { co_return result::current_exception(); diff --git a/lix/libstore/remote-store.hh b/lix/libstore/remote-store.hh index 4d628111c..c07eeef25 100644 --- a/lix/libstore/remote-store.hh +++ b/lix/libstore/remote-store.hh @@ -57,7 +57,8 @@ public: kj::Promise> queryAllValidPaths() override; - std::shared_ptr queryPathInfoUncached(const StorePath & path) override; + kj::Promise>> + queryPathInfoUncached(const StorePath & path) override; kj::Promise> queryReferrers(const StorePath & path, StorePathSet & referrers) override; diff --git a/lix/libstore/s3-binary-cache-store.cc b/lix/libstore/s3-binary-cache-store.cc index b452b87f5..6efa52cbc 100644 --- a/lix/libstore/s3-binary-cache-store.cc +++ b/lix/libstore/s3-binary-cache-store.cc @@ -315,7 +315,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore a GET is unlikely to be slower than HEAD. */ kj::Promise> isValidPathUncached(const StorePath & storePath) override try { - queryPathInfo(storePath); + TRY_AWAIT(queryPathInfo(storePath)); co_return true; } catch (InvalidPath & e) { co_return false; diff --git a/lix/libstore/store-api.cc b/lix/libstore/store-api.cc index 11ef9af2d..66d460a1c 100644 --- a/lix/libstore/store-api.cc +++ b/lix/libstore/store-api.cc @@ -21,6 +21,7 @@ #include "lix/libstore/worker-protocol.hh" #include "lix/libutil/users.hh" +#include #include #include #include @@ -600,7 +601,7 @@ try { debug("checking substituter '%s' for path '%s'", sub->getUri(), sub->printStorePath(subPath)); try { - auto info = sub->queryPathInfo(subPath); + auto info = TRY_AWAIT(sub->queryPathInfo(subPath)); if (sub->config().storeDir != config().storeDir && !(info->isContentAddressed(*sub) && info->references.empty())) @@ -671,7 +672,7 @@ try { queryPathInfoUncached(). */ kj::Promise> Store::isValidPathUncached(const StorePath & path) try { - queryPathInfo(path); + TRY_AWAIT(queryPathInfo(path)); co_return true; } catch (InvalidPath &) { co_return false; @@ -696,8 +697,8 @@ static void ensureGoodStorePath(Store * store, const StorePath & expected, const } -ref Store::queryPathInfo(const StorePath & storePath) -{ +kj::Promise>> Store::queryPathInfo(const StorePath & storePath) +try { auto hashPart = std::string(storePath.hashPart()); { @@ -706,7 +707,7 @@ ref Store::queryPathInfo(const StorePath & storePath) stats.narInfoReadAverted++; if (!res->didExist()) throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath)); - return ref(res->value); + co_return ref(res->value); } } @@ -721,11 +722,11 @@ ref Store::queryPathInfo(const StorePath & storePath) if (res.first == NarInfoDiskCache::oInvalid) throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath)); } - return ref(res.second); + co_return ref(res.second); } } - auto info = queryPathInfoUncached(storePath); + auto info = TRY_AWAIT(queryPathInfoUncached(storePath)); if (info) { // first, before we cache anything, check that the store gave us valid data. ensureGoodStorePath(this, storePath, info->path); @@ -745,7 +746,9 @@ ref Store::queryPathInfo(const StorePath & storePath) throw InvalidPath("path '%s' does not exist in the store", printStorePath(storePath)); } - return ref(info); + co_return ref(info); +} catch (...) { + co_return result::current_exception(); } kj::Promise>> Store::queryRealisation(const DrvOutput & id) @@ -823,14 +826,14 @@ try { std::condition_variable wakeup; ThreadPool pool{"queryValidPaths pool"}; - auto doQuery = [&](const StorePath & path) { + auto doQuery = [&](AsyncIoRoot & aio, const StorePath & path) { checkInterrupt(); bool exists = false; std::exception_ptr newExc{}; try { - queryPathInfo(path); + aio.blockOn(queryPathInfo(path)); exists = true; } catch (InvalidPath &) { } catch (...) { @@ -853,7 +856,7 @@ try { }; for (auto & path : paths) - pool.enqueue(std::bind(doQuery, path)); + pool.enqueueWithAio(std::bind(doQuery, std::placeholders::_1, path)); TRY_AWAIT(pool.processAsync()); @@ -881,7 +884,7 @@ try { for (auto & i : paths) { s += printStorePath(i) + "\n"; - auto info = queryPathInfo(i); + auto info = TRY_AWAIT(queryPathInfo(i)); if (showHash) { s += info->narHash.to_string(Base::Base16, false) + "\n"; @@ -952,7 +955,7 @@ try { auto& jsonPath = jsonList.emplace_back(json::object()); try { - auto info = queryPathInfo(storePath); + auto info = TRY_AWAIT(queryPathInfo(storePath)); jsonPath["path"] = printStorePath(info->path); jsonPath["valid"] = true; @@ -1024,7 +1027,7 @@ try { StorePathSet closure; TRY_AWAIT(computeFSClosure(storePath, closure, false, false)); for (auto & p : closure) { - auto info = queryPathInfo(p); + auto info = TRY_AWAIT(queryPathInfo(p)); totalNarSize += info->narSize; auto narInfo = std::dynamic_pointer_cast( std::shared_ptr(info)); @@ -1106,7 +1109,7 @@ try { {storePathS, srcUri, dstUri}); PushActivity pact(act.id); - auto info = srcStore.queryPathInfo(storePath); + auto info = TRY_AWAIT(srcStore.queryPathInfo(storePath)); // recompute store path on the chance dstStore does it differently if (info->ca && info->references.empty()) { @@ -1239,7 +1242,7 @@ try { }; for (auto & missingPath : sortedMissing) { - auto info = srcStore.queryPathInfo(missingPath); + auto info = TRY_AWAIT(srcStore.queryPathInfo(missingPath)); auto storePathForDst = computeStorePathForDst(*info); pathsMap.insert_or_assign(missingPath, storePathForDst); @@ -1411,7 +1414,7 @@ try { if (!path.isDerivation()) { try { - auto info = queryPathInfo(path); + auto info = TRY_AWAIT(queryPathInfo(path)); co_return info->deriver; } catch (InvalidPath &) { co_return std::nullopt; diff --git a/lix/libstore/store-api.hh b/lix/libstore/store-api.hh index b0c1d17dd..d0a2f4c89 100644 --- a/lix/libstore/store-api.hh +++ b/lix/libstore/store-api.hh @@ -385,7 +385,7 @@ public: * Query information about a valid path. It is permitted to omit * the name part of the store path. */ - ref queryPathInfo(const StorePath & path); + kj::Promise>> queryPathInfo(const StorePath & path); /** * Query the information about a realisation. @@ -420,7 +420,8 @@ protected: * Queries the path info without caching. * Note to implementors: should return `nullptr` when the path is not found. */ - virtual std::shared_ptr queryPathInfoUncached(const StorePath & path) = 0; + virtual kj::Promise>> + queryPathInfoUncached(const StorePath & path) = 0; virtual kj::Promise>> queryRealisationUncached(const DrvOutput &) = 0; diff --git a/lix/nix/diff-closures.cc b/lix/nix/diff-closures.cc index 14469c0dc..cdb1480de 100644 --- a/lix/nix/diff-closures.cc +++ b/lix/nix/diff-closures.cc @@ -67,17 +67,22 @@ try { auto & beforeVersions = beforeClosure[name]; auto & afterVersions = afterClosure[name]; - auto totalSize = [&](const std::map> & versions) - { - uint64_t sum = 0; - for (auto & [_, paths] : versions) - for (auto & [path, _] : paths) - sum += store->queryPathInfo(path)->narSize; - return sum; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines) + auto totalSize = [&](const std::map> & versions + ) -> kj::Promise> { + try { + uint64_t sum = 0; + for (auto & [_, paths] : versions) + for (auto & [path, _] : paths) + sum += TRY_AWAIT(store->queryPathInfo(path))->narSize; + co_return sum; + } catch (...) { + co_return result::current_exception(); + } }; - auto beforeSize = totalSize(beforeVersions); - auto afterSize = totalSize(afterVersions); + auto beforeSize = TRY_AWAIT(totalSize(beforeVersions)); + auto afterSize = TRY_AWAIT(totalSize(afterVersions)); auto sizeDelta = (int64_t) afterSize - (int64_t) beforeSize; auto showDelta = std::abs(sizeDelta) >= 8 * 1024; diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index aec484416..39eda9a48 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -1439,7 +1439,7 @@ struct CmdFlakePrefetch : FlakeCommand, MixJSON auto originalRef = getFlakeRef(); auto resolvedRef = aio().blockOn(originalRef.resolve(store)); auto [tree, lockedRef] = aio().blockOn(resolvedRef.fetchTree(store)); - auto hash = store->queryPathInfo(tree.storePath)->narHash; + auto hash = aio().blockOn(store->queryPathInfo(tree.storePath))->narHash; if (json) { auto res = nlohmann::json::object(); diff --git a/lix/nix/path-info.cc b/lix/nix/path-info.cc index e98b8d153..75283ce01 100644 --- a/lix/nix/path-info.cc +++ b/lix/nix/path-info.cc @@ -2,6 +2,7 @@ #include "lix/libmain/shared.hh" #include "lix/libstore/store-api.hh" #include "lix/libmain/common-args.hh" +#include "lix/libutil/async.hh" #include #include @@ -100,7 +101,7 @@ struct CmdPathInfo : StorePathsCommand, MixJSON else { for (auto & storePath : storePaths) { - auto info = store->queryPathInfo(storePath); + auto info = aio().blockOn(store->queryPathInfo(storePath)); auto storePathS = store->printStorePath(info->path); std::cout << storePathS; diff --git a/lix/nix/sigs.cc b/lix/nix/sigs.cc index 63d736004..7ab26a5c1 100644 --- a/lix/nix/sigs.cc +++ b/lix/nix/sigs.cc @@ -50,13 +50,13 @@ struct CmdCopySigs : StorePathsCommand auto storePath = store->parseStorePath(storePathS); - auto info = store->queryPathInfo(storePath); + auto info = aio.blockOn(store->queryPathInfo(storePath)); StringSet newSigs; for (auto & store2 : substituters) { try { - auto info2 = store2->queryPathInfo(info->path); + auto info2 = aio.blockOn(store2->queryPathInfo(info->path)); /* Don't import signatures that don't match this binary. */ @@ -130,7 +130,7 @@ struct CmdSign : StorePathsCommand auto storePath = store->parseStorePath(storePathS); - auto info = store->queryPathInfo(storePath); + auto info = aio.blockOn(store->queryPathInfo(storePath)); auto info2(*info); info2.sigs.clear(); diff --git a/lix/nix/verify.cc b/lix/nix/verify.cc index 4f233297d..45a505233 100644 --- a/lix/nix/verify.cc +++ b/lix/nix/verify.cc @@ -90,7 +90,7 @@ struct CmdVerify : StorePathsCommand MaintainCount> mcActive(active); update(); - auto info = store->queryPathInfo(storePath); + auto info = aio.blockOn(store->queryPathInfo(storePath)); // Note: info->path can be different from storePath // for binary cache stores when using --all (since we @@ -143,7 +143,7 @@ struct CmdVerify : StorePathsCommand for (auto & store2 : substituters) { if (validSigs >= actualSigsNeeded) break; try { - auto info2 = store2->queryPathInfo(info->path); + auto info2 = aio.blockOn(store2->queryPathInfo(info->path)); if (info2->isContentAddressed(*store)) validSigs = ValidPathInfo::maxSigs; doSigs(info2->sigs); } catch (InvalidPath &) { diff --git a/lix/nix/why-depends.cc b/lix/nix/why-depends.cc index d5fa6cdea..6c1853986 100644 --- a/lix/nix/why-depends.cc +++ b/lix/nix/why-depends.cc @@ -132,7 +132,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions for (auto & path : closure) graph.emplace(path, Node { .path = path, - .refs = store->queryPathInfo(path)->references, + .refs = aio().blockOn(store->queryPathInfo(path))->references, .dist = path == dependencyPath ? 0 : inf }); diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs index 033852c74..b7fcd2473 100644 --- a/perl/lib/Nix/Store.xs +++ b/perl/lib/Nix/Store.xs @@ -79,7 +79,7 @@ int isValidPath(char * path) SV * queryReferences(char * path) PPCODE: try { - for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->references) + for (auto & i : aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->references) XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); @@ -89,7 +89,7 @@ SV * queryReferences(char * path) SV * queryPathHash(char * path) PPCODE: try { - auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base::Base32, true); + auto s = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path)))->narHash.to_string(Base::Base32, true); XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0))); } catch (Error & e) { croak("%s", e.what()); @@ -99,7 +99,7 @@ SV * queryPathHash(char * path) SV * queryDeriver(char * path) PPCODE: try { - auto info = store()->queryPathInfo(store()->parseStorePath(path)); + auto info = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path))); if (!info->deriver) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0))); } catch (Error & e) { @@ -110,7 +110,7 @@ SV * queryDeriver(char * path) SV * queryPathInfo(char * path, int base32) PPCODE: try { - auto info = store()->queryPathInfo(store()->parseStorePath(path)); + auto info = aio().blockOn(store()->queryPathInfo(store()->parseStorePath(path))); if (!info->deriver) XPUSHs(&PL_sv_undef); else