libstore: asyncify Store::isValidPath
Change-Id: I2b98781c04944282fd1219cbec0804fd1ceb6765
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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_(
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user