mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
Merge pull request #13753 from obsidiansystems/simplify-derivation-goal
Simplify `DerivationGoal` in many ways
This commit is contained in:
commit
4e776a5be8
5 changed files with 182 additions and 234 deletions
|
|
@ -151,6 +151,33 @@ std::string showKnownOutputs(Store & store, const Derivation & drv)
|
||||||
produced using a substitute. So we have to build instead. */
|
produced using a substitute. So we have to build instead. */
|
||||||
Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution()
|
Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution()
|
||||||
{
|
{
|
||||||
|
/* Recheck at goal start. In particular, whereas before we were
|
||||||
|
given this information by the downstream goal, that cannot happen
|
||||||
|
anymore if the downstream goal only cares about one output, but
|
||||||
|
we care about all outputs. */
|
||||||
|
auto outputHashes = staticOutputHashes(worker.evalStore, *drv);
|
||||||
|
for (auto & [outputName, outputHash] : outputHashes) {
|
||||||
|
InitialOutput v{
|
||||||
|
.wanted = true, // Will be refined later
|
||||||
|
.outputHash = outputHash};
|
||||||
|
|
||||||
|
/* TODO we might want to also allow randomizing the paths
|
||||||
|
for regular CA derivations, e.g. for sake of checking
|
||||||
|
determinism. */
|
||||||
|
if (drv->type().isImpure()) {
|
||||||
|
v.known = InitialOutputStatus{
|
||||||
|
.path = StorePath::random(outputPathName(drv->name, outputName)),
|
||||||
|
.status = PathStatus::Absent,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
initialOutputs.insert({
|
||||||
|
outputName,
|
||||||
|
std::move(v),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
checkPathValidity();
|
||||||
|
|
||||||
Goals waitees;
|
Goals waitees;
|
||||||
|
|
||||||
std::map<ref<const SingleDerivedPath>, GoalPtr, value_comparison> inputGoals;
|
std::map<ref<const SingleDerivedPath>, GoalPtr, value_comparison> inputGoals;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,13 @@ DerivationGoal::DerivationGoal(
|
||||||
: Goal(worker, haveDerivation())
|
: Goal(worker, haveDerivation())
|
||||||
, drvPath(drvPath)
|
, drvPath(drvPath)
|
||||||
, wantedOutput(wantedOutput)
|
, wantedOutput(wantedOutput)
|
||||||
|
, outputHash{[&] {
|
||||||
|
if (auto * mOutputHash = get(staticOutputHashes(worker.evalStore, drv), wantedOutput))
|
||||||
|
return *mOutputHash;
|
||||||
|
else
|
||||||
|
throw Error(
|
||||||
|
"derivation '%s' does not have output '%s'", worker.store.printStorePath(drvPath), wantedOutput);
|
||||||
|
}()}
|
||||||
, buildMode(buildMode)
|
, buildMode(buildMode)
|
||||||
{
|
{
|
||||||
this->drv = std::make_unique<Derivation>(drv);
|
this->drv = std::make_unique<Derivation>(drv);
|
||||||
|
|
@ -74,95 +81,21 @@ Goal::Co DerivationGoal::haveDerivation()
|
||||||
if (!drv->type().hasKnownOutputPaths())
|
if (!drv->type().hasKnownOutputPaths())
|
||||||
experimentalFeatureSettings.require(Xp::CaDerivations);
|
experimentalFeatureSettings.require(Xp::CaDerivations);
|
||||||
|
|
||||||
/* At least one of the output paths could not be
|
|
||||||
produced using a substitute. So we have to build instead. */
|
|
||||||
auto gaveUpOnSubstitution = [&]() -> Goal::Co {
|
|
||||||
auto g = worker.makeDerivationBuildingGoal(drvPath, *drv, buildMode);
|
|
||||||
|
|
||||||
/* We will finish with it ourselves, as if we were the derivational goal. */
|
|
||||||
g->preserveException = true;
|
|
||||||
|
|
||||||
// TODO move into constructor
|
|
||||||
g->initialOutputs = initialOutputs;
|
|
||||||
|
|
||||||
{
|
|
||||||
Goals waitees;
|
|
||||||
waitees.insert(g);
|
|
||||||
co_await await(std::move(waitees));
|
|
||||||
}
|
|
||||||
|
|
||||||
trace("outer build done");
|
|
||||||
|
|
||||||
buildResult = g->buildResult;
|
|
||||||
|
|
||||||
if (buildMode == bmCheck) {
|
|
||||||
/* In checking mode, the builder will not register any outputs.
|
|
||||||
So we want to make sure the ones that we wanted to check are
|
|
||||||
properly there. */
|
|
||||||
buildResult.builtOutputs = assertPathValidity();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = buildResult.builtOutputs.begin(); it != buildResult.builtOutputs.end();) {
|
|
||||||
if (it->first != wantedOutput) {
|
|
||||||
it = buildResult.builtOutputs.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildResult.success())
|
|
||||||
assert(buildResult.builtOutputs.count(wantedOutput) > 0);
|
|
||||||
|
|
||||||
co_return amDone(g->exitCode, g->ex);
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto & i : drv->outputsAndOptPaths(worker.store))
|
for (auto & i : drv->outputsAndOptPaths(worker.store))
|
||||||
if (i.second.second)
|
if (i.second.second)
|
||||||
worker.store.addTempRoot(*i.second.second);
|
worker.store.addTempRoot(*i.second.second);
|
||||||
|
|
||||||
{
|
|
||||||
bool impure = drv->type().isImpure();
|
|
||||||
|
|
||||||
if (impure)
|
|
||||||
experimentalFeatureSettings.require(Xp::ImpureDerivations);
|
|
||||||
|
|
||||||
auto outputHashes = staticOutputHashes(worker.evalStore, *drv);
|
|
||||||
for (auto & [outputName, outputHash] : outputHashes) {
|
|
||||||
InitialOutput v{
|
|
||||||
.wanted = true, // Will be refined later
|
|
||||||
.outputHash = outputHash};
|
|
||||||
|
|
||||||
/* TODO we might want to also allow randomizing the paths
|
|
||||||
for regular CA derivations, e.g. for sake of checking
|
|
||||||
determinism. */
|
|
||||||
if (impure) {
|
|
||||||
v.known = InitialOutputStatus{
|
|
||||||
.path = StorePath::random(outputPathName(drv->name, outputName)),
|
|
||||||
.status = PathStatus::Absent,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
initialOutputs.insert({
|
|
||||||
outputName,
|
|
||||||
std::move(v),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (impure) {
|
|
||||||
/* We don't yet have any safe way to cache an impure derivation at
|
/* We don't yet have any safe way to cache an impure derivation at
|
||||||
this step. */
|
this step. */
|
||||||
co_return gaveUpOnSubstitution();
|
if (drv->type().isImpure()) {
|
||||||
}
|
experimentalFeatureSettings.require(Xp::ImpureDerivations);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
{
|
|
||||||
/* Check what outputs paths are not already valid. */
|
/* Check what outputs paths are not already valid. */
|
||||||
auto [allValid, validOutputs] = checkPathValidity();
|
auto checkResult = checkPathValidity();
|
||||||
|
|
||||||
/* If they are all valid, then we're done. */
|
/* If they are all valid, then we're done. */
|
||||||
if (allValid && buildMode == bmNormal) {
|
if (checkResult && checkResult->second == PathStatus::Valid && buildMode == bmNormal) {
|
||||||
co_return done(BuildResult::AlreadyValid, std::move(validOutputs));
|
co_return done(BuildResult::AlreadyValid, checkResult->first);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Goals waitees;
|
Goals waitees;
|
||||||
|
|
@ -170,17 +103,14 @@ Goal::Co DerivationGoal::haveDerivation()
|
||||||
/* We are first going to try to create the invalid output paths
|
/* We are first going to try to create the invalid output paths
|
||||||
through substitutes. If that doesn't work, we'll build
|
through substitutes. If that doesn't work, we'll build
|
||||||
them. */
|
them. */
|
||||||
if (settings.useSubstitutes && drvOptions.substitutesAllowed())
|
if (settings.useSubstitutes && drvOptions.substitutesAllowed()) {
|
||||||
for (auto & [outputName, status] : initialOutputs) {
|
if (!checkResult)
|
||||||
if (!status.wanted)
|
|
||||||
continue;
|
|
||||||
if (!status.known)
|
|
||||||
waitees.insert(upcast_goal(worker.makeDrvOutputSubstitutionGoal(
|
waitees.insert(upcast_goal(worker.makeDrvOutputSubstitutionGoal(
|
||||||
DrvOutput{status.outputHash, outputName}, buildMode == bmRepair ? Repair : NoRepair)));
|
DrvOutput{outputHash, wantedOutput}, buildMode == bmRepair ? Repair : NoRepair)));
|
||||||
else {
|
else {
|
||||||
auto * cap = getDerivationCA(*drv);
|
auto * cap = getDerivationCA(*drv);
|
||||||
waitees.insert(upcast_goal(worker.makePathSubstitutionGoal(
|
waitees.insert(upcast_goal(worker.makePathSubstitutionGoal(
|
||||||
status.known->path,
|
checkResult->first.outPath,
|
||||||
buildMode == bmRepair ? Repair : NoRepair,
|
buildMode == bmRepair ? Repair : NoRepair,
|
||||||
cap ? std::optional{*cap} : std::nullopt)));
|
cap ? std::optional{*cap} : std::nullopt)));
|
||||||
}
|
}
|
||||||
|
|
@ -203,20 +133,61 @@ Goal::Co DerivationGoal::haveDerivation()
|
||||||
|
|
||||||
nrFailed = nrNoSubstituters = 0;
|
nrFailed = nrNoSubstituters = 0;
|
||||||
|
|
||||||
auto [allValid, validOutputs] = checkPathValidity();
|
checkResult = checkPathValidity();
|
||||||
|
|
||||||
|
bool allValid = checkResult && checkResult->second == PathStatus::Valid;
|
||||||
|
|
||||||
if (buildMode == bmNormal && allValid) {
|
if (buildMode == bmNormal && allValid) {
|
||||||
co_return done(BuildResult::Substituted, std::move(validOutputs));
|
co_return done(BuildResult::Substituted, checkResult->first);
|
||||||
}
|
}
|
||||||
if (buildMode == bmRepair && allValid) {
|
if (buildMode == bmRepair && allValid) {
|
||||||
co_return repairClosure();
|
co_return repairClosure();
|
||||||
}
|
}
|
||||||
if (buildMode == bmCheck && !allValid)
|
if (buildMode == bmCheck && !allValid)
|
||||||
throw Error(
|
throw Error(
|
||||||
"some outputs of '%s' are not valid, so checking is not possible", worker.store.printStorePath(drvPath));
|
"some outputs of '%s' are not valid, so checking is not possible",
|
||||||
|
worker.store.printStorePath(drvPath));
|
||||||
|
}
|
||||||
|
|
||||||
/* Nothing to wait for; tail call */
|
/* Give up on substitution for the output we want, actually build this derivation */
|
||||||
co_return gaveUpOnSubstitution();
|
|
||||||
|
auto g = worker.makeDerivationBuildingGoal(drvPath, *drv, buildMode);
|
||||||
|
|
||||||
|
/* We will finish with it ourselves, as if we were the derivational goal. */
|
||||||
|
g->preserveException = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
Goals waitees;
|
||||||
|
waitees.insert(g);
|
||||||
|
co_await await(std::move(waitees));
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("outer build done");
|
||||||
|
|
||||||
|
buildResult = g->buildResult;
|
||||||
|
|
||||||
|
if (buildMode == bmCheck) {
|
||||||
|
/* In checking mode, the builder will not register any outputs.
|
||||||
|
So we want to make sure the ones that we wanted to check are
|
||||||
|
properly there. */
|
||||||
|
buildResult.builtOutputs = {{wantedOutput, assertPathValidity()}};
|
||||||
|
} else {
|
||||||
|
/* Otherwise the builder will give us info for out output, but
|
||||||
|
also for other outputs. Filter down to just our output so as
|
||||||
|
not to leak info on unrelated things. */
|
||||||
|
for (auto it = buildResult.builtOutputs.begin(); it != buildResult.builtOutputs.end();) {
|
||||||
|
if (it->first != wantedOutput) {
|
||||||
|
it = buildResult.builtOutputs.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildResult.success())
|
||||||
|
assert(buildResult.builtOutputs.count(wantedOutput) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
co_return amDone(g->exitCode, g->ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -253,7 +224,7 @@ Goal::Co DerivationGoal::repairClosure()
|
||||||
}();
|
}();
|
||||||
|
|
||||||
StorePathSet outputClosure;
|
StorePathSet outputClosure;
|
||||||
if (auto mPath = get(outputs, wantedOutput)) {
|
if (auto * mPath = get(outputs, wantedOutput)) {
|
||||||
worker.store.computeFSClosure(*mPath, outputClosure);
|
worker.store.computeFSClosure(*mPath, outputClosure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,100 +285,63 @@ Goal::Co DerivationGoal::repairClosure()
|
||||||
co_return done(BuildResult::AlreadyValid, assertPathValidity());
|
co_return done(BuildResult::AlreadyValid, assertPathValidity());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<bool, SingleDrvOutputs> DerivationGoal::checkPathValidity()
|
std::optional<std::pair<Realisation, PathStatus>> DerivationGoal::checkPathValidity()
|
||||||
{
|
{
|
||||||
if (drv->type().isImpure())
|
if (drv->type().isImpure())
|
||||||
return {false, {}};
|
return std::nullopt;
|
||||||
|
|
||||||
bool checkHash = buildMode == bmRepair;
|
auto drvOutput = DrvOutput{outputHash, wantedOutput};
|
||||||
StringSet wantedOutputsLeft{wantedOutput};
|
|
||||||
SingleDrvOutputs validOutputs;
|
|
||||||
|
|
||||||
auto partialDerivationOutputMap = [&] {
|
std::optional<Realisation> mRealisation;
|
||||||
for (auto * drvStore : {&worker.evalStore, &worker.store})
|
|
||||||
if (drvStore->isValidPath(drvPath))
|
|
||||||
return worker.store.queryPartialDerivationOutputMap(drvPath, drvStore);
|
|
||||||
|
|
||||||
/* In-memory derivation will naturally fall back on this case, where
|
if (auto * mOutput = get(drv->outputs, wantedOutput)) {
|
||||||
we do best-effort with static information. */
|
if (auto mPath = mOutput->path(worker.store, drv->name, wantedOutput)) {
|
||||||
std::map<std::string, std::optional<StorePath>> res;
|
mRealisation = Realisation{drvOutput, std::move(*mPath)};
|
||||||
for (auto & [name, output] : drv->outputs)
|
|
||||||
res.insert_or_assign(name, output.path(worker.store, drv->name, name));
|
|
||||||
return res;
|
|
||||||
}();
|
|
||||||
|
|
||||||
for (auto & i : partialDerivationOutputMap) {
|
|
||||||
auto initialOutput = get(initialOutputs, i.first);
|
|
||||||
if (!initialOutput)
|
|
||||||
// this is an invalid output, gets caught with (!wantedOutputsLeft.empty())
|
|
||||||
continue;
|
|
||||||
auto & info = *initialOutput;
|
|
||||||
info.wanted = wantedOutput == i.first;
|
|
||||||
if (info.wanted)
|
|
||||||
wantedOutputsLeft.erase(i.first);
|
|
||||||
if (i.second) {
|
|
||||||
auto outputPath = *i.second;
|
|
||||||
info.known = {
|
|
||||||
.path = outputPath,
|
|
||||||
.status = !worker.store.isValidPath(outputPath) ? PathStatus::Absent
|
|
||||||
: !checkHash || worker.pathContentsGood(outputPath) ? PathStatus::Valid
|
|
||||||
: PathStatus::Corrupt,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
auto drvOutput = DrvOutput{info.outputHash, i.first};
|
} else {
|
||||||
|
throw Error(
|
||||||
|
"derivation '%s' does not have wanted outputs '%s'", worker.store.printStorePath(drvPath), wantedOutput);
|
||||||
|
}
|
||||||
|
|
||||||
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
|
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
|
||||||
if (auto real = worker.store.queryRealisation(drvOutput)) {
|
for (auto * drvStore : {&worker.evalStore, &worker.store}) {
|
||||||
info.known = {
|
if (auto real = drvStore->queryRealisation(drvOutput)) {
|
||||||
.path = real->outPath,
|
mRealisation = *real;
|
||||||
.status = PathStatus::Valid,
|
break;
|
||||||
};
|
}
|
||||||
} else if (info.known && info.known->isValid()) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRealisation) {
|
||||||
|
auto & outputPath = mRealisation->outPath;
|
||||||
|
bool checkHash = buildMode == bmRepair;
|
||||||
|
PathStatus status = !worker.store.isValidPath(outputPath) ? PathStatus::Absent
|
||||||
|
: !checkHash || worker.pathContentsGood(outputPath) ? PathStatus::Valid
|
||||||
|
: PathStatus::Corrupt;
|
||||||
|
|
||||||
|
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations) && status == PathStatus::Valid) {
|
||||||
// We know the output because it's a static output of the
|
// We know the output because it's a static output of the
|
||||||
// derivation, and the output path is valid, but we don't have
|
// derivation, and the output path is valid, but we don't have
|
||||||
// its realisation stored (probably because it has been built
|
// its realisation stored (probably because it has been built
|
||||||
// without the `ca-derivations` experimental flag).
|
// without the `ca-derivations` experimental flag).
|
||||||
worker.store.registerDrvOutput(
|
worker.store.registerDrvOutput(*mRealisation);
|
||||||
Realisation{
|
|
||||||
drvOutput,
|
|
||||||
info.known->path,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (info.known && info.known->isValid())
|
|
||||||
validOutputs.emplace(i.first, Realisation{drvOutput, info.known->path});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we requested all the outputs, we are always fine.
|
return {{*mRealisation, status}};
|
||||||
// If we requested specific elements, the loop above removes all the valid
|
} else
|
||||||
// ones, so any that are left must be invalid.
|
return std::nullopt;
|
||||||
if (!wantedOutputsLeft.empty())
|
|
||||||
throw Error(
|
|
||||||
"derivation '%s' does not have wanted outputs %s",
|
|
||||||
worker.store.printStorePath(drvPath),
|
|
||||||
concatStringsSep(", ", quoteStrings(wantedOutputsLeft)));
|
|
||||||
|
|
||||||
bool allValid = true;
|
|
||||||
for (auto & [_, status] : initialOutputs) {
|
|
||||||
if (!status.wanted)
|
|
||||||
continue;
|
|
||||||
if (!status.known || !status.known->isValid()) {
|
|
||||||
allValid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {allValid, validOutputs};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleDrvOutputs DerivationGoal::assertPathValidity()
|
Realisation DerivationGoal::assertPathValidity()
|
||||||
{
|
{
|
||||||
auto [allValid, validOutputs] = checkPathValidity();
|
auto checkResult = checkPathValidity();
|
||||||
if (!allValid)
|
if (!(checkResult && checkResult->second == PathStatus::Valid))
|
||||||
throw Error("some outputs are unexpectedly invalid");
|
throw Error("some outputs are unexpectedly invalid");
|
||||||
return validOutputs;
|
return checkResult->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
Goal::Done DerivationGoal::done(BuildResult::Status status, SingleDrvOutputs builtOutputs, std::optional<Error> ex)
|
Goal::Done
|
||||||
|
DerivationGoal::done(BuildResult::Status status, std::optional<Realisation> builtOutput, std::optional<Error> ex)
|
||||||
{
|
{
|
||||||
buildResult.status = status;
|
buildResult.status = status;
|
||||||
if (ex)
|
if (ex)
|
||||||
|
|
@ -420,9 +354,8 @@ Goal::Done DerivationGoal::done(BuildResult::Status status, SingleDrvOutputs bui
|
||||||
mcExpectedBuilds.reset();
|
mcExpectedBuilds.reset();
|
||||||
|
|
||||||
if (buildResult.success()) {
|
if (buildResult.success()) {
|
||||||
auto wantedBuiltOutputs = filterDrvOutputs(OutputsSpec::Names{wantedOutput}, std::move(builtOutputs));
|
assert(builtOutput);
|
||||||
assert(!wantedBuiltOutputs.empty());
|
buildResult.builtOutputs = {{wantedOutput, std::move(*builtOutput)}};
|
||||||
buildResult.builtOutputs = std::move(wantedBuiltOutputs);
|
|
||||||
if (status == BuildResult::Built)
|
if (status == BuildResult::Built)
|
||||||
worker.doneBuilds++;
|
worker.doneBuilds++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -70,14 +70,14 @@ private:
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<Derivation> drv;
|
std::unique_ptr<Derivation> drv;
|
||||||
|
|
||||||
|
const Hash outputHash;
|
||||||
|
|
||||||
|
const BuildMode buildMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The remainder is state held during the build.
|
* The remainder is state held during the build.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::map<std::string, InitialOutput> initialOutputs;
|
|
||||||
|
|
||||||
BuildMode buildMode;
|
|
||||||
|
|
||||||
std::unique_ptr<MaintainCount<uint64_t>> mcExpectedBuilds;
|
std::unique_ptr<MaintainCount<uint64_t>> mcExpectedBuilds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -86,22 +86,29 @@ private:
|
||||||
Co haveDerivation();
|
Co haveDerivation();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update 'initialOutputs' to determine the current status of the
|
* Return `std::nullopt` if the output is unknown, e.g. un unbuilt
|
||||||
* outputs of the derivation. Also returns a Boolean denoting
|
* floating content-addressing derivation. Otherwise, returns a pair
|
||||||
* whether all outputs are valid and non-corrupt, and a
|
* of a `Realisation`, containing among other things the store path
|
||||||
* 'SingleDrvOutputs' structure containing the valid outputs.
|
* of the wanted output, and a `PathStatus` with the
|
||||||
|
* current status of that output.
|
||||||
*/
|
*/
|
||||||
std::pair<bool, SingleDrvOutputs> checkPathValidity();
|
std::optional<std::pair<Realisation, PathStatus>> checkPathValidity();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts if any output is not valid or corrupt, and otherwise
|
* Aborts if any output is not valid or corrupt, and otherwise
|
||||||
* returns a 'SingleDrvOutputs' structure containing all outputs.
|
* returns a 'Realisation' for the wanted output.
|
||||||
*/
|
*/
|
||||||
SingleDrvOutputs assertPathValidity();
|
Realisation assertPathValidity();
|
||||||
|
|
||||||
Co repairClosure();
|
Co repairClosure();
|
||||||
|
|
||||||
Done done(BuildResult::Status status, SingleDrvOutputs builtOutputs = {}, std::optional<Error> ex = {});
|
/**
|
||||||
|
* @param builtOutput Must be set if `status` is successful.
|
||||||
|
*/
|
||||||
|
Done done(
|
||||||
|
BuildResult::Status status,
|
||||||
|
std::optional<Realisation> builtOutput = std::nullopt,
|
||||||
|
std::optional<Error> ex = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace nix
|
} // namespace nix
|
||||||
|
|
|
||||||
|
|
@ -102,13 +102,6 @@ typedef std::map<OutputName, Realisation> SingleDrvOutputs;
|
||||||
*/
|
*/
|
||||||
typedef std::map<DrvOutput, Realisation> DrvOutputs;
|
typedef std::map<DrvOutput, Realisation> DrvOutputs;
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter a SingleDrvOutputs to include only specific output names
|
|
||||||
*
|
|
||||||
* Moves the `outputs` input.
|
|
||||||
*/
|
|
||||||
SingleDrvOutputs filterDrvOutputs(const OutputsSpec &, SingleDrvOutputs &&);
|
|
||||||
|
|
||||||
struct OpaquePath
|
struct OpaquePath
|
||||||
{
|
{
|
||||||
StorePath path;
|
StorePath path;
|
||||||
|
|
|
||||||
|
|
@ -135,18 +135,6 @@ size_t Realisation::checkSignatures(const PublicKeys & publicKeys) const
|
||||||
return good;
|
return good;
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleDrvOutputs filterDrvOutputs(const OutputsSpec & wanted, SingleDrvOutputs && outputs)
|
|
||||||
{
|
|
||||||
SingleDrvOutputs ret = std::move(outputs);
|
|
||||||
for (auto it = ret.begin(); it != ret.end();) {
|
|
||||||
if (!wanted.contains(it->first))
|
|
||||||
it = ret.erase(it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorePath RealisedPath::path() const
|
StorePath RealisedPath::path() const
|
||||||
{
|
{
|
||||||
return std::visit([](auto && arg) { return arg.getPath(); }, raw);
|
return std::visit([](auto && arg) { return arg.getPath(); }, raw);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue