mirror of
https://github.com/NixOS/nix
synced 2025-06-25 06:31:14 +02:00
Merge pull request #12412 from obsidiansystems/simplify-state-machine-2
Simplify state machine 2
This commit is contained in:
commit
3e8cd2ffe6
2 changed files with 68 additions and 74 deletions
|
@ -382,79 +382,7 @@ Goal::Co DerivationGoal::gaveUpOnSubstitution()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!waitees.empty()) co_await Suspend{}; /* to prevent hang (no wake-up event) */
|
if (!waitees.empty()) co_await Suspend{}; /* to prevent hang (no wake-up event) */
|
||||||
co_return inputsRealised();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Goal::Co DerivationGoal::repairClosure()
|
|
||||||
{
|
|
||||||
assert(!drv->type().isImpure());
|
|
||||||
|
|
||||||
/* If we're repairing, we now know that our own outputs are valid.
|
|
||||||
Now check whether the other paths in the outputs closure are
|
|
||||||
good. If not, then start derivation goals for the derivations
|
|
||||||
that produced those outputs. */
|
|
||||||
|
|
||||||
/* Get the output closure. */
|
|
||||||
auto outputs = queryDerivationOutputMap();
|
|
||||||
StorePathSet outputClosure;
|
|
||||||
for (auto & i : outputs) {
|
|
||||||
if (!wantedOutputs.contains(i.first)) continue;
|
|
||||||
worker.store.computeFSClosure(i.second, outputClosure);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Filter out our own outputs (which we have already checked). */
|
|
||||||
for (auto & i : outputs)
|
|
||||||
outputClosure.erase(i.second);
|
|
||||||
|
|
||||||
/* Get all dependencies of this derivation so that we know which
|
|
||||||
derivation is responsible for which path in the output
|
|
||||||
closure. */
|
|
||||||
StorePathSet inputClosure;
|
|
||||||
if (useDerivation) worker.store.computeFSClosure(drvPath, inputClosure);
|
|
||||||
std::map<StorePath, StorePath> outputsToDrv;
|
|
||||||
for (auto & i : inputClosure)
|
|
||||||
if (i.isDerivation()) {
|
|
||||||
auto depOutputs = worker.store.queryPartialDerivationOutputMap(i, &worker.evalStore);
|
|
||||||
for (auto & j : depOutputs)
|
|
||||||
if (j.second)
|
|
||||||
outputsToDrv.insert_or_assign(*j.second, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check each path (slow!). */
|
|
||||||
for (auto & i : outputClosure) {
|
|
||||||
if (worker.pathContentsGood(i)) continue;
|
|
||||||
printError(
|
|
||||||
"found corrupted or missing path '%s' in the output closure of '%s'",
|
|
||||||
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
|
||||||
auto drvPath2 = outputsToDrv.find(i);
|
|
||||||
if (drvPath2 == outputsToDrv.end())
|
|
||||||
addWaitee(upcast_goal(worker.makePathSubstitutionGoal(i, Repair)));
|
|
||||||
else
|
|
||||||
addWaitee(worker.makeGoal(
|
|
||||||
DerivedPath::Built {
|
|
||||||
.drvPath = makeConstantStorePathRef(drvPath2->second),
|
|
||||||
.outputs = OutputsSpec::All { },
|
|
||||||
},
|
|
||||||
bmRepair));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitees.empty()) {
|
|
||||||
co_return done(BuildResult::AlreadyValid, assertPathValidity());
|
|
||||||
} else {
|
|
||||||
co_await Suspend{};
|
|
||||||
|
|
||||||
trace("closure repaired");
|
|
||||||
if (nrFailed > 0)
|
|
||||||
throw Error("some paths in the output closure of derivation '%s' could not be repaired",
|
|
||||||
worker.store.printStorePath(drvPath));
|
|
||||||
co_return done(BuildResult::AlreadyValid, assertPathValidity());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Goal::Co DerivationGoal::inputsRealised()
|
|
||||||
{
|
|
||||||
trace("all inputs realised");
|
trace("all inputs realised");
|
||||||
|
|
||||||
if (nrFailed != 0) {
|
if (nrFailed != 0) {
|
||||||
|
@ -744,6 +672,73 @@ Goal::Co DerivationGoal::tryLocalBuild() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Goal::Co DerivationGoal::repairClosure()
|
||||||
|
{
|
||||||
|
assert(!drv->type().isImpure());
|
||||||
|
|
||||||
|
/* If we're repairing, we now know that our own outputs are valid.
|
||||||
|
Now check whether the other paths in the outputs closure are
|
||||||
|
good. If not, then start derivation goals for the derivations
|
||||||
|
that produced those outputs. */
|
||||||
|
|
||||||
|
/* Get the output closure. */
|
||||||
|
auto outputs = queryDerivationOutputMap();
|
||||||
|
StorePathSet outputClosure;
|
||||||
|
for (auto & i : outputs) {
|
||||||
|
if (!wantedOutputs.contains(i.first)) continue;
|
||||||
|
worker.store.computeFSClosure(i.second, outputClosure);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter out our own outputs (which we have already checked). */
|
||||||
|
for (auto & i : outputs)
|
||||||
|
outputClosure.erase(i.second);
|
||||||
|
|
||||||
|
/* Get all dependencies of this derivation so that we know which
|
||||||
|
derivation is responsible for which path in the output
|
||||||
|
closure. */
|
||||||
|
StorePathSet inputClosure;
|
||||||
|
if (useDerivation) worker.store.computeFSClosure(drvPath, inputClosure);
|
||||||
|
std::map<StorePath, StorePath> outputsToDrv;
|
||||||
|
for (auto & i : inputClosure)
|
||||||
|
if (i.isDerivation()) {
|
||||||
|
auto depOutputs = worker.store.queryPartialDerivationOutputMap(i, &worker.evalStore);
|
||||||
|
for (auto & j : depOutputs)
|
||||||
|
if (j.second)
|
||||||
|
outputsToDrv.insert_or_assign(*j.second, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check each path (slow!). */
|
||||||
|
for (auto & i : outputClosure) {
|
||||||
|
if (worker.pathContentsGood(i)) continue;
|
||||||
|
printError(
|
||||||
|
"found corrupted or missing path '%s' in the output closure of '%s'",
|
||||||
|
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
||||||
|
auto drvPath2 = outputsToDrv.find(i);
|
||||||
|
if (drvPath2 == outputsToDrv.end())
|
||||||
|
addWaitee(upcast_goal(worker.makePathSubstitutionGoal(i, Repair)));
|
||||||
|
else
|
||||||
|
addWaitee(worker.makeGoal(
|
||||||
|
DerivedPath::Built {
|
||||||
|
.drvPath = makeConstantStorePathRef(drvPath2->second),
|
||||||
|
.outputs = OutputsSpec::All { },
|
||||||
|
},
|
||||||
|
bmRepair));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitees.empty()) {
|
||||||
|
co_return done(BuildResult::AlreadyValid, assertPathValidity());
|
||||||
|
} else {
|
||||||
|
co_await Suspend{};
|
||||||
|
|
||||||
|
trace("closure repaired");
|
||||||
|
if (nrFailed > 0)
|
||||||
|
throw Error("some paths in the output closure of derivation '%s' could not be repaired",
|
||||||
|
worker.store.printStorePath(drvPath));
|
||||||
|
co_return done(BuildResult::AlreadyValid, assertPathValidity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void chmod_(const Path & path, mode_t mode)
|
static void chmod_(const Path & path, mode_t mode)
|
||||||
{
|
{
|
||||||
if (chmod(path.c_str(), mode) == -1)
|
if (chmod(path.c_str(), mode) == -1)
|
||||||
|
|
|
@ -80,7 +80,7 @@ struct DerivationGoal : public Goal
|
||||||
/**
|
/**
|
||||||
* Mapping from input derivations + output names to actual store
|
* Mapping from input derivations + output names to actual store
|
||||||
* paths. This is filled in by waiteeDone() as each dependency
|
* paths. This is filled in by waiteeDone() as each dependency
|
||||||
* finishes, before inputsRealised() is reached.
|
* finishes, before `trace("all inputs realised")` is reached.
|
||||||
*/
|
*/
|
||||||
std::map<std::pair<StorePath, std::string>, StorePath> inputDrvOutputs;
|
std::map<std::pair<StorePath, std::string>, StorePath> inputDrvOutputs;
|
||||||
|
|
||||||
|
@ -235,7 +235,6 @@ struct DerivationGoal : public Goal
|
||||||
Co init() override;
|
Co init() override;
|
||||||
Co haveDerivation();
|
Co haveDerivation();
|
||||||
Co gaveUpOnSubstitution();
|
Co gaveUpOnSubstitution();
|
||||||
Co inputsRealised();
|
|
||||||
Co tryToBuild();
|
Co tryToBuild();
|
||||||
virtual Co tryLocalBuild();
|
virtual Co tryLocalBuild();
|
||||||
Co buildDone();
|
Co buildDone();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue