libstore: asyncify Store::isValidPath

Change-Id: I2b98781c04944282fd1219cbec0804fd1ceb6765
This commit is contained in:
eldritch horrors
2025-03-05 18:49:45 +01:00
parent fb2a808604
commit 90caba8489
28 changed files with 120 additions and 94 deletions
+1 -1
View File
@@ -368,7 +368,7 @@ connected:
auto outputPaths = drv.outputsAndOptPaths(*store);
for (auto & [outputName, hopefullyOutputPath] : outputPaths) {
assert(hopefullyOutputPath.second);
if (!store->isValidPath(*hopefullyOutputPath.second))
if (!aio.blockOn(store->isValidPath(*hopefullyOutputPath.second)))
missingPaths.insert(*hopefullyOutputPath.second);
}
}
+1 -1
View File
@@ -230,7 +230,7 @@ static std::strong_ordering comparePriorities(EvalState & state, DrvInfo & drv1,
static bool isPrebuilt(EvalState & state, DrvInfo & elem)
{
auto path = elem.queryOutPath(state);
if (state.ctx.store->isValidPath(path)) return true;
if (state.aio.blockOn(state.ctx.store->isValidPath(path))) return true;
return state.aio.blockOn(state.ctx.store->querySubstitutablePaths({path})).count(path);
}
+3 -3
View File
@@ -103,7 +103,7 @@ try {
else {
if (build) TRY_AWAIT(store->ensurePath(path.path));
else if (!store->isValidPath(path.path))
else if (!TRY_AWAIT(store->isValidPath(path.path)))
throw Error("path '%s' does not exist and cannot be created", store->printStorePath(path.path));
if (store2) {
if (gcRoot == "")
@@ -563,7 +563,7 @@ static void registerValidity(AsyncIoRoot & aio, bool reregister, bool hashGiven,
auto hashResultOpt = !hashGiven ? std::optional<HashResult> { {Hash::dummy, -1} } : std::nullopt;
auto info = decodeValidPathInfo(*store, cin, hashResultOpt);
if (!info) break;
if (!store->isValidPath(info->path) || reregister) {
if (!aio.blockOn(store->isValidPath(info->path)) || reregister) {
/* !!! races */
if (canonicalise)
canonicalisePathMetaData(store->printStorePath(info->path), {});
@@ -615,7 +615,7 @@ static void opCheckValidity(AsyncIoRoot & aio, Strings opFlags, Strings opArgs)
for (auto & i : opArgs) {
auto path = store->followLinksToStorePath(i);
if (!store->isValidPath(path)) {
if (!aio.blockOn(store->isValidPath(path))) {
if (printInvalid)
cout << fmt("%s\n", store->printStorePath(path));
else
+1 -1
View File
@@ -495,7 +495,7 @@ StorePath NixRepl::getDerivationPath(Value & v) {
auto drvPath = drvInfo->queryDrvPath(state);
if (!drvPath)
throw Error("expression did not evaluate to a valid derivation (no 'drvPath' attribute)");
if (!evaluator.store->isValidPath(*drvPath))
if (!state.aio.blockOn(evaluator.store->isValidPath(*drvPath)))
throw Error("expression evaluated to invalid derivation '%s'", evaluator.store->printStorePath(*drvPath));
return *drvPath;
}
+4 -3
View File
@@ -2,6 +2,7 @@
#include "lix/libstore/sqlite.hh"
#include "lix/libexpr/eval.hh"
#include "lix/libstore/store-api.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/users.hh"
namespace nix::eval_cache {
@@ -585,7 +586,7 @@ string_t AttrCursor::getStringWithContext(EvalState & state)
return o.path;
},
}, c.raw);
if (!state.ctx.store->isValidPath(path)) {
if (!state.aio.blockOn(state.ctx.store->isValidPath(path))) {
valid = false;
break;
}
@@ -729,11 +730,11 @@ StorePath AttrCursor::forceDerivation(EvalState & state)
{
auto aDrvPath = getAttr(state, "drvPath");
auto drvPath = state.ctx.store->parseStorePath(aDrvPath->getString(state));
if (!state.ctx.store->isValidPath(drvPath) && !settings.readOnlyMode) {
if (!state.aio.blockOn(state.ctx.store->isValidPath(drvPath)) && !settings.readOnlyMode) {
/* The eval cache contains 'drvPath', but the actual path has
been garbage-collected. So force it to be regenerated. */
aDrvPath->forceValue(state);
if (!state.ctx.store->isValidPath(drvPath))
if (!state.aio.blockOn(state.ctx.store->isValidPath(drvPath)))
throw Error("don't know how to recreate store derivation '%s'!",
state.ctx.store->printStorePath(drvPath));
}
+18 -10
View File
@@ -17,8 +17,10 @@
#include "lix/libexpr/value-to-xml.hh"
#include "lix/libexpr/primops.hh"
#include "lix/libfetchers/fetch-to-store.hh"
#include "lix/libutil/result.hh"
#include <boost/container/small_vector.hpp>
#include <kj/async.h>
#include <nlohmann/json.hpp>
#include <sys/types.h>
@@ -46,30 +48,36 @@ try {
StringMap res;
for (auto & c : context) {
auto ensureValid = [&](const StorePath & p) {
if (!store->isValidPath(p))
errors.make<InvalidPathError>(store->printStorePath(p)).debugThrow();
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
auto ensureValid = [&](const StorePath & p) -> kj::Promise<Result<void>> {
try {
if (!TRY_AWAIT(store->isValidPath(p)))
errors.make<InvalidPathError>(store->printStorePath(p)).debugThrow();
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
};
std::visit(overloaded {
TRY_AWAIT(std::visit(overloaded {
[&](const NixStringContextElem::Built & b) {
drvs.push_back(DerivedPath::Built {
.drvPath = b.drvPath,
.outputs = OutputsSpec::Names { b.output },
});
ensureValid(b.drvPath->getBaseStorePath());
return ensureValid(b.drvPath->getBaseStorePath());
},
[&](const NixStringContextElem::Opaque & o) {
auto ctxS = store->printStorePath(o.path);
res.insert_or_assign(ctxS, ctxS);
ensureValid(o.path);
return ensureValid(o.path);
},
[&](const NixStringContextElem::DrvDeep & d) {
/* Treat same as Opaque */
auto ctxS = store->printStorePath(d.drvPath);
res.insert_or_assign(ctxS, ctxS);
ensureValid(d.drvPath);
return ensureValid(d.drvPath);
},
}, c.raw);
}, c.raw));
}
if (drvs.empty()) co_return StringMap{};
@@ -184,7 +192,7 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v
if (!state.ctx.store->isStorePath(path2))
return std::nullopt;
auto storePath = state.ctx.store->parseStorePath(path2);
if (!(state.ctx.store->isValidPath(storePath) && isDerivation(path2)))
if (!(state.aio.blockOn(state.ctx.store->isValidPath(storePath)) && isDerivation(path2)))
return std::nullopt;
return storePath;
};
@@ -1565,7 +1573,7 @@ static void addPath(
.references = {},
});
if (!expectedHash || !state.ctx.store->isValidPath(*expectedStorePath)) {
if (!expectedHash || !state.aio.blockOn(state.ctx.store->isValidPath(*expectedStorePath))) {
auto checkedPath = state.ctx.paths.checkSourcePath(CanonPath(realPath));
auto dstPath = state.aio.blockOn(
method == FileIngestionMethod::Flat
+4 -3
View File
@@ -2,6 +2,7 @@
#include "lix/libexpr/extra-primops.hh"
#include "lix/libstore/store-api.hh"
#include "lix/libstore/make-content-addressed.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/url.hh"
namespace nix {
@@ -19,7 +20,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
// establish toPath or throw
if (!toPathMaybe || !state.ctx.store->isValidPath(*toPathMaybe)) {
if (!toPathMaybe || !state.aio.blockOn(state.ctx.store->isValidPath(*toPathMaybe))) {
auto rewrittenPath =
state.aio.blockOn(makeContentAddressed(fromStore, *state.ctx.store, fromPath));
if (toPathMaybe && *toPathMaybe != rewrittenPath)
@@ -67,7 +68,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
*/
static void runFetchClosureWithContentAddressedPath(EvalState & state, const PosIdx pos, Store & fromStore, const StorePath & fromPath, Value & v) {
if (!state.ctx.store->isValidPath(fromPath))
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);
@@ -93,7 +94,7 @@ static void runFetchClosureWithContentAddressedPath(EvalState & state, const Pos
*/
static void runFetchClosureWithInputAddressedPath(EvalState & state, const PosIdx pos, Store & fromStore, const StorePath & fromPath, Value & v) {
if (!state.ctx.store->isValidPath(fromPath))
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);
+1 -1
View File
@@ -262,7 +262,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
.references = {}
});
if (state.ctx.store->isValidPath(expectedPath)) {
if (state.aio.blockOn(state.ctx.store->isValidPath(expectedPath))) {
state.ctx.paths.allowAndSetStorePathString(expectedPath, v);
return;
}
+1 -1
View File
@@ -110,7 +110,7 @@ struct CacheImpl : Cache
auto timestamp = stmt.getInt(3);
TRY_AWAIT(store->addTempRoot(storePath));
if (!store->isValidPath(storePath)) {
if (!TRY_AWAIT(store->isValidPath(storePath))) {
// FIXME: we could try to substitute 'storePath'.
debug("ignoring disappeared cache entry '%s'", inAttrsJSON);
co_return std::nullopt;
+3 -1
View File
@@ -131,7 +131,9 @@ struct PathInputScheme : InputScheme
TRY_AWAIT(store->addTempRoot(*storePath));
time_t mtime = 0;
if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) {
if (!storePath || storePath->name() != "source"
|| !TRY_AWAIT(store->isValidPath(*storePath)))
{
// FIXME: try to substitute storePath.
auto src = AsyncGeneratorInputStream{dumpPathAndGetMtime(absPath, mtime)};
storePath = TRY_AWAIT(store->addToStoreFromDump(src, "source"));
+2 -2
View File
@@ -277,7 +277,7 @@ kj::Promise<Result<void>> BinaryCacheStore::addToStore(
CheckSigsFlag checkSigs
)
try {
if (!repair && isValidPath(info.path)) {
if (!repair && TRY_AWAIT(isValidPath(info.path))) {
// FIXME: copyNAR -> null sink
TRY_AWAIT(narSource.drain());
co_return result::success();
@@ -477,7 +477,7 @@ try {
auto textHash = hashString(HashType::SHA256, s);
auto path = makeTextPath(name, TextInfo { { textHash }, references });
if (!repair && isValidPath(path))
if (!repair && TRY_AWAIT(isValidPath(path)))
co_return path;
StringSink sink;
+11 -11
View File
@@ -170,7 +170,7 @@ try {
/* The first thing to do is to make sure that the derivation
exists. If it doesn't, it may be created through a
substitute. */
if (buildMode == bmNormal && worker.evalStore.isValidPath(drvPath)) {
if (buildMode == bmNormal && TRY_AWAIT(worker.evalStore.isValidPath(drvPath))) {
co_return co_await loadDerivation();
}
@@ -205,7 +205,7 @@ try {
- Dynamic derivations are built, and so are found in the main store.
*/
for (auto * drvStore : { &worker.evalStore, &worker.store }) {
if (drvStore->isValidPath(drvPath)) {
if (TRY_AWAIT(drvStore->isValidPath(drvPath))) {
drv = std::make_unique<Derivation>(TRY_AWAIT(drvStore->readDerivation(drvPath)));
break;
}
@@ -232,7 +232,7 @@ try {
for (auto & [outputName, output] : drv->outputs) {
auto randomPath = StorePath::random(outputPathName(drv->name, outputName));
assert(!worker.store.isValidPath(randomPath));
assert(!TRY_AWAIT(worker.store.isValidPath(randomPath)));
initialOutputs.insert({
outputName,
InitialOutput {
@@ -431,13 +431,13 @@ try {
if (&worker.evalStore != &worker.store) {
RealisedPath::Set inputSrcs;
for (auto & i : drv->inputSrcs)
if (worker.evalStore.isValidPath(i))
if (TRY_AWAIT(worker.evalStore.isValidPath(i)))
inputSrcs.insert(i);
TRY_AWAIT(copyClosure(worker.evalStore, worker.store, inputSrcs));
}
for (auto & i : drv->inputSrcs) {
if (worker.store.isValidPath(i)) continue;
if (TRY_AWAIT(worker.store.isValidPath(i))) continue;
if (!settings.useSubstitutes)
throw Error("dependency '%s' of '%s' does not exist, and substitution is disabled",
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
@@ -648,9 +648,9 @@ try {
co_return *outPath;
}
else {
auto outMap = worker.evalStore.isValidPath(depDrvPath)
auto outMap = TRY_AWAIT(worker.evalStore.isValidPath(depDrvPath))
? TRY_AWAIT(worker.store.queryDerivationOutputMap(depDrvPath, &worker.evalStore))
: worker.store.isValidPath(depDrvPath)
: TRY_AWAIT(worker.store.isValidPath(depDrvPath))
? TRY_AWAIT(worker.store.queryDerivationOutputMap(depDrvPath, &worker.store))
: (assert(false), OutputPathMap{});
@@ -1191,7 +1191,7 @@ try {
newRealisation.id = DrvOutput { initialOutput->outputHash, outputName };
newRealisation.signatures.clear();
if (!drv->type().isFixed()) {
auto & drvStore = worker.evalStore.isValidPath(drvPath)
auto & drvStore = TRY_AWAIT(worker.evalStore.isValidPath(drvPath))
? worker.evalStore
: worker.store;
newRealisation.dependentRealisations = TRY_AWAIT(
@@ -1619,7 +1619,7 @@ try {
co_return res;
} else {
for (auto * drvStore : {&worker.evalStore, &worker.store}) {
if (drvStore->isValidPath(drvPath)) {
if (TRY_AWAIT(drvStore->isValidPath(drvPath))) {
co_return TRY_AWAIT(worker.store.queryPartialDerivationOutputMap(drvPath, drvStore)
);
}
@@ -1640,7 +1640,7 @@ try {
co_return res;
} else {
for (auto * drvStore : {&worker.evalStore, &worker.store}) {
if (drvStore->isValidPath(drvPath)) {
if (TRY_AWAIT(drvStore->isValidPath(drvPath))) {
co_return TRY_AWAIT(worker.store.queryDerivationOutputMap(drvPath, drvStore));
}
}
@@ -1679,7 +1679,7 @@ try {
auto outputPath = *i.second;
info.known = {
.path = outputPath,
.status = !worker.store.isValidPath(outputPath)
.status = !TRY_AWAIT(worker.store.isValidPath(outputPath))
? PathStatus::Absent
: !checkHash || TRY_AWAIT(worker.pathContentsGood(outputPath))
? PathStatus::Valid
+2 -2
View File
@@ -110,7 +110,7 @@ try {
kj::Promise<Result<void>> Store::ensurePath(const StorePath & path)
try {
/* If the path is already valid, we're done. */
if (isValidPath(path)) co_return result::success();
if (TRY_AWAIT(isValidPath(path))) co_return result::success();
auto results = TRY_AWAIT(processGoals(*this, *this, [&](GoalFactory & gf) {
Worker::Targets goals;
@@ -146,7 +146,7 @@ try {
/* Since substituting the path didn't work, if we have a valid
deriver, then rebuild the deriver. */
auto info = queryPathInfo(path);
if (info->deriver && isValidPath(*info->deriver)) {
if (info->deriver && TRY_AWAIT(isValidPath(*info->deriver))) {
TRY_AWAIT(processGoals(*this, *this, [&](GoalFactory & gf) {
Worker::Targets goals;
goals.emplace_back(gf.makeGoal(
+2 -2
View File
@@ -2386,7 +2386,7 @@ try {
} else if (buildMode == bmCheck) {
/* Path already exists, and we want to compare, so we leave out
new path in place. */
} else if (worker.store.isValidPath(newInfo.path)) {
} else if (TRY_AWAIT(worker.store.isValidPath(newInfo.path))) {
/* Path already exists because CA path produced by something
else. No moving needed. */
assert(newInfo.ca);
@@ -2402,7 +2402,7 @@ try {
if (buildMode == bmCheck) {
if (!worker.store.isValidPath(newInfo.path)) continue;
if (!TRY_AWAIT(worker.store.isValidPath(newInfo.path))) continue;
ValidPathInfo oldInfo(*worker.store.queryPathInfo(newInfo.path));
if (newInfo.narHash != oldInfo.narHash) {
anyCheckMismatchSeen = true;
+8 -6
View File
@@ -55,7 +55,7 @@ try {
TRY_AWAIT(worker.store.addTempRoot(storePath));
/* If the path already exists we're done. */
if (!repair && worker.store.isValidPath(storePath)) {
if (!repair && TRY_AWAIT(worker.store.isValidPath(storePath))) {
co_return done(ecSuccess, BuildResult::AlreadyValid);
}
@@ -180,19 +180,21 @@ try {
trace("all references realised");
if (nrFailed > 0) {
return {done(
co_return done(
nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed,
BuildResult::DependencyFailed,
fmt("some references of path '%s' could not be realised", worker.store.printStorePath(storePath)))};
fmt("some references of path '%s' could not be realised",
worker.store.printStorePath(storePath))
);
}
for (auto & i : info->references)
if (i != storePath) /* ignore self-references */
assert(worker.store.isValidPath(i));
assert(TRY_AWAIT(worker.store.isValidPath(i)));
return tryToRun();
co_return TRY_AWAIT(tryToRun());
} catch (...) {
return {result::current_exception()};
co_return result::current_exception();
}
+1 -1
View File
@@ -275,7 +275,7 @@ static void performOp(AsyncIoRoot & aio, TunnelLogger * logger, ref<Store> store
case WorkerProto::Op::IsValidPath: {
auto path = store->parseStorePath(readString(from));
logger->startWork();
bool result = store->isValidPath(path);
bool result = aio.blockOn(store->isValidPath(path));
logger->stopWork();
to << result;
break;
+14 -9
View File
@@ -257,14 +257,19 @@ void LocalStore::findTempRoots(Roots & tempRoots, bool censor)
kj::Promise<Result<void>>
LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
try {
auto foundRoot = [&](const Path & path, const Path & target) {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
auto foundRoot = [&](const Path & path, const Path & target) -> kj::Promise<Result<void>> {
try {
auto storePath = toStorePath(target).first;
if (isValidPath(storePath))
if (TRY_AWAIT(isValidPath(storePath)))
roots[std::move(storePath)].emplace(path);
else
printInfo("skipping invalid root from '%1%' to '%2%'", path, target);
} catch (BadStorePath &) { }
} catch (BadStorePath &) {
} catch (...) {
co_return result::current_exception();
}
co_return result::success();
};
try {
@@ -280,7 +285,7 @@ try {
else if (type == DT_LNK) {
Path target = readLink(path);
if (isInStore(target))
foundRoot(path, target);
TRY_AWAIT(foundRoot(path, target));
/* Handle indirect roots. */
else {
@@ -294,7 +299,7 @@ try {
struct stat st2 = lstat(target);
if (!S_ISLNK(st2.st_mode)) co_return result::success();
Path target2 = readLink(target);
if (isInStore(target2)) foundRoot(target, target2);
if (isInStore(target2)) TRY_AWAIT(foundRoot(target, target2));
}
}
}
@@ -302,7 +307,7 @@ try {
else if (type == DT_REG) {
auto storePath =
maybeParseStorePath(config().storeDir + "/" + std::string(baseNameOf(path)));
if (storePath && isValidPath(*storePath))
if (storePath && TRY_AWAIT(isValidPath(*storePath)))
roots[std::move(*storePath)].emplace(path);
}
@@ -380,7 +385,7 @@ try {
if (!isInStore(target)) continue;
try {
auto path = toStorePath(target).first;
if (!isValidPath(path)) continue;
if (!TRY_AWAIT(isValidPath(path))) continue;
debug("got additional root '%1%'", printStorePath(path));
if (censor)
roots[path].insert(censored);
@@ -754,7 +759,7 @@ try {
co_return result::success();
}
if (isValidPath(*path)) {
if (TRY_AWAIT(isValidPath(*path))) {
/* Visit the referrers of this path. */
auto i = referrersCache.find(*path);
@@ -774,7 +779,7 @@ try {
TRY_AWAIT(queryPartialDerivationOutputMap(*path)))
{
if (maybeOutPath &&
isValidPath(*maybeOutPath) &&
TRY_AWAIT(isValidPath(*maybeOutPath)) &&
queryPathInfo(*maybeOutPath)->deriver == *path)
enqueue(*maybeOutPath);
}
+2 -2
View File
@@ -17,7 +17,7 @@ struct LocalStoreAccessor : public FSAccessor
kj::Promise<Result<Path>> toRealPath(const Path & path, bool requireValidPath = true)
try {
auto storePath = store->toStorePath(path).first;
if (requireValidPath && !store->isValidPath(storePath))
if (requireValidPath && !TRY_AWAIT(store->isValidPath(storePath)))
throw InvalidPath("path '%1%' does not exist in the store", store->printStorePath(storePath));
co_return store->getRealStoreDir() + std::string(path, store->config().storeDir.size());
} catch (...) {
@@ -86,7 +86,7 @@ ref<FSAccessor> LocalFSStore::getFSAccessor()
kj::Promise<Result<box_ptr<Source>>> LocalFSStore::narFromPath(const StorePath & path)
try {
if (!isValidPath(path))
if (!TRY_AWAIT(isValidPath(path)))
throw Error("path '%s' does not exist in store", printStorePath(path));
co_return make_box_ptr<GeneratorSource>(
dumpPath(getRealStoreDir() + std::string(printStorePath(path), config().storeDir.size()))
+14 -10
View File
@@ -1018,7 +1018,7 @@ LocalStore::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubs
try {
StorePathSet res;
for (auto & i : paths)
if (isValidPath(i)) res.insert(i);
if (TRY_AWAIT(isValidPath(i))) res.insert(i);
co_return res;
} catch (...) {
co_return result::current_exception();
@@ -1310,7 +1310,7 @@ try {
TRY_AWAIT(addTempRoot(info.path));
if (repair || !isValidPath(info.path)) {
if (repair || !TRY_AWAIT(isValidPath(info.path))) {
std::optional<PathLock> outputLock;
@@ -1322,7 +1322,7 @@ try {
if (!locksHeld.count(printStorePath(info.path)))
outputLock = TRY_AWAIT(lockPathAsync(realPath));
if (repair || !isValidPath(info.path)) {
if (repair || !TRY_AWAIT(isValidPath(info.path))) {
deletePath(realPath);
@@ -1495,7 +1495,7 @@ try {
TRY_AWAIT(addTempRoot(dstPath));
if (repair || !isValidPath(dstPath)) {
if (repair || !TRY_AWAIT(isValidPath(dstPath))) {
/* The first check above is an optimisation to prevent
unnecessary lock acquisition. */
@@ -1504,7 +1504,7 @@ try {
PathLock outputLock = TRY_AWAIT(lockPathAsync(realPath));
if (repair || !isValidPath(dstPath)) {
if (repair || !TRY_AWAIT(isValidPath(dstPath))) {
deletePath(realPath);
@@ -1565,13 +1565,13 @@ try {
TRY_AWAIT(addTempRoot(dstPath));
if (repair || !isValidPath(dstPath)) {
if (repair || !TRY_AWAIT(isValidPath(dstPath))) {
auto realPath = Store::toRealPath(dstPath);
PathLock outputLock = TRY_AWAIT(lockPathAsync(realPath));
if (repair || !isValidPath(dstPath)) {
if (repair || !TRY_AWAIT(isValidPath(dstPath))) {
deletePath(realPath);
@@ -1725,6 +1725,7 @@ try {
Hash nullHash(HashType::SHA256);
for (auto & i : validPaths) {
std::optional<Error> caught;
try {
auto info = std::const_pointer_cast<ValidPathInfo>(std::shared_ptr<const ValidPathInfo>(queryPathInfo(i)));
@@ -1766,12 +1767,15 @@ try {
}
} catch (Error & e) {
caught = std::move(e);
}
if (caught) {
/* It's possible that the path got GC'ed, so ignore
errors on invalid paths. */
if (isValidPath(i))
logError(e.info());
if (TRY_AWAIT(isValidPath(i)))
logError(caught->info());
else
warn(e.msg());
warn(caught->msg());
errors = true;
}
}
+7 -7
View File
@@ -37,7 +37,7 @@ try {
if (includeDerivers && path.isDerivation())
for (auto& [_, maybeOutPath] : TRY_AWAIT(queryPartialDerivationOutputMap(path)))
if (maybeOutPath && isValidPath(*maybeOutPath))
if (maybeOutPath && TRY_AWAIT(isValidPath(*maybeOutPath)))
res.insert(*maybeOutPath);
co_return res;
} catch (...) {
@@ -56,10 +56,10 @@ try {
if (includeOutputs && path.isDerivation())
for (auto& [_, maybeOutPath] : TRY_AWAIT(queryPartialDerivationOutputMap(path)))
if (maybeOutPath && isValidPath(*maybeOutPath))
if (maybeOutPath && TRY_AWAIT(isValidPath(*maybeOutPath)))
res.insert(*maybeOutPath);
if (includeDerivers && info->deriver && isValidPath(*info->deriver))
if (includeDerivers && info->deriver && TRY_AWAIT(isValidPath(*info->deriver)))
res.insert(*info->deriver);
co_return res;
} catch (...) {
@@ -236,7 +236,7 @@ struct QueryMissingContext
}
auto & drvPath = drvPathP->path;
if (!store.isValidPath(drvPath)) {
if (!aio.blockOn(store.isValidPath(drvPath))) {
// FIXME: we could try to substitute the derivation.
auto state(state_.lock());
state->unknown.insert(drvPath);
@@ -254,7 +254,7 @@ struct QueryMissingContext
knownOutputPaths = false;
break;
}
if (bfd.outputs.contains(outputName) && !store.isValidPath(*pathOpt))
if (bfd.outputs.contains(outputName) && !aio.blockOn(store.isValidPath(*pathOpt)))
invalid.insert(*pathOpt);
}
if (knownOutputPaths && invalid.empty()) return;
@@ -280,7 +280,7 @@ struct QueryMissingContext
if (!realisation)
continue;
found = true;
if (!store.isValidPath(realisation->outPath))
if (!aio.blockOn(store.isValidPath(realisation->outPath)))
invalid.insert(realisation->outPath);
break;
}
@@ -306,7 +306,7 @@ struct QueryMissingContext
void doPathOpaque(AsyncIoRoot & aio, const DerivedPath::Opaque & bo)
{
if (store.isValidPath(bo.path)) return;
if (aio.blockOn(store.isValidPath(bo.path))) return;
SubstitutablePathInfos infos;
aio.blockOn(store.querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos));
+2 -1
View File
@@ -1,5 +1,6 @@
#include "lix/libstore/local-store.hh"
#include "lix/libstore/globals.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/result.hh"
#include "lix/libutil/signals.hh"
#include "lix/libutil/strings.hh"
@@ -270,7 +271,7 @@ try {
for (auto & i : paths) {
TRY_AWAIT(addTempRoot(i));
if (!isValidPath(i)) continue; /* path was GC'ed, probably */
if (!TRY_AWAIT(isValidPath(i))) continue; /* path was GC'ed, probably */
{
Activity act(*logger, lvlTalkative, actUnknown, fmt("optimising path '%s'", printStorePath(i)));
optimisePath_(
+1 -1
View File
@@ -58,7 +58,7 @@ try {
auto [storePath, restPath] = store->toStorePath(path);
if (requireValidPath && !store->isValidPath(storePath))
if (requireValidPath && !TRY_AWAIT(store->isValidPath(storePath)))
throw InvalidPath("path '%1%' does not exist in remote store", store->printStorePath(storePath));
auto i = nars.find(std::string(storePath.hashPart()));
+12 -10
View File
@@ -339,7 +339,7 @@ try {
auto & [info, _] = *infosMap.at(path);
if (isValidPath(info.path)) {
if (aio.blockOn(isValidPath(info.path))) {
nrDone++;
showProgress();
return StorePathSet();
@@ -365,7 +365,7 @@ try {
LegacySSHStore::narFromPath()'s connection lock. */
auto source = std::move(source_);
if (!isValidPath(info.path)) {
if (!aio.blockOn(isValidPath(info.path))) {
MaintainCount<decltype(nrRunning)> mc(nrRunning);
showProgress();
try {
@@ -463,7 +463,7 @@ try {
};
info.narSize = narSize;
if (!isValidPath(info.path)) {
if (!TRY_AWAIT(isValidPath(info.path))) {
auto source = AsyncGeneratorInputStream{dumpPath(srcPath)};
TRY_AWAIT(addToStore(info, source));
}
@@ -633,14 +633,14 @@ try {
}
bool Store::isValidPath(const StorePath & storePath)
{
kj::Promise<Result<bool>> Store::isValidPath(const StorePath & storePath)
try {
{
auto state_(state.lock());
auto res = state_->pathInfoCache.get(std::string(storePath.to_string()));
if (res && res->isKnownNow()) {
stats.narInfoReadAverted++;
return res->didExist();
co_return res->didExist();
}
}
@@ -651,7 +651,7 @@ bool Store::isValidPath(const StorePath & storePath)
auto state_(state.lock());
state_->pathInfoCache.upsert(std::string(storePath.to_string()),
res.first == NarInfoDiskCache::oInvalid ? PathInfoCacheValue{} : PathInfoCacheValue { .value = res.second });
return res.first == NarInfoDiskCache::oValid;
co_return res.first == NarInfoDiskCache::oValid;
}
}
@@ -661,7 +661,9 @@ bool Store::isValidPath(const StorePath & storePath)
// FIXME: handle valid = true case.
diskCache->upsertNarInfo(getUri(), std::string(storePath.hashPart()), 0);
return valid;
co_return valid;
} catch (...) {
co_return result::current_exception();
}
@@ -1093,7 +1095,7 @@ kj::Promise<Result<void>> copyStorePath(
try {
/* Bail out early (before starting a download from srcStore) if
dstStore already has this path. */
if (!repair && dstStore.isValidPath(storePath))
if (!repair && TRY_AWAIT(dstStore.isValidPath(storePath)))
co_return result::success();
auto srcUri = srcStore.getUri();
@@ -1416,7 +1418,7 @@ try {
}
}
if (!experimentalFeatureSettings.isEnabled(Xp::CaDerivations) || !isValidPath(path))
if (!experimentalFeatureSettings.isEnabled(Xp::CaDerivations) || !TRY_AWAIT(isValidPath(path)))
co_return path;
auto drv = TRY_AWAIT(readDerivation(path));
+1 -1
View File
@@ -346,7 +346,7 @@ public:
* Check whether a path is valid.
* A path is valid when it exists in the store *now*.
*/
bool isValidPath(const StorePath & path);
kj::Promise<Result<bool>> isValidPath(const StorePath & path);
protected:
+1 -1
View File
@@ -270,7 +270,7 @@ try {
{
assert(optPath);
auto & outPath = *optPath;
assert(store->isValidPath(outPath));
assert(TRY_AWAIT(store->isValidPath(outPath)));
auto outPathS = store->toRealPath(outPath);
if (lstat(outPathS).st_size)
co_return outPath;
+1 -1
View File
@@ -79,7 +79,7 @@ std::tuple<StorePath, Hash> prefetchFile(
.hash = *expectedHash,
.references = {},
});
if (store->isValidPath(*storePath))
if (aio.blockOn(store->isValidPath(*storePath)))
hash = expectedHash;
else
storePath.reset();
+1 -1
View File
@@ -195,7 +195,7 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand
);
}
if (!store->isValidPath(store->parseStorePath(userEnv))) {
if (!aio().blockOn(store->isValidPath(store->parseStorePath(userEnv)))) {
throw Error("directory '%s' is not in the Nix store", userEnv);
}
+1 -1
View File
@@ -68,7 +68,7 @@ void setVerbosity(int level)
int isValidPath(char * path)
CODE:
try {
RETVAL = store()->isValidPath(store()->parseStorePath(path));
RETVAL = aio().blockOn(store()->isValidPath(store()->parseStorePath(path)));
} catch (Error & e) {
croak("%s", e.what());
}