1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-17 16:02:43 +01:00

Simplify DerivationGoal by just storing a singular initialOutput

We know we want exactly want output in `DerivationGoal` now (since
recent refactors), so we can start simplifying things to take advantage
of this.
This commit is contained in:
John Ericson 2025-07-09 17:47:28 -04:00
parent 4b6edfcfc7
commit 14173d761c
2 changed files with 40 additions and 57 deletions

View file

@ -24,15 +24,16 @@
namespace nix { namespace nix {
DerivationGoal::DerivationGoal( DerivationGoal::DerivationGoal(const StorePath & drvPath, const Derivation & drv,
const StorePath & drvPath, const OutputName & wantedOutput, Worker & worker, BuildMode buildMode)
const Derivation & drv,
const OutputName & wantedOutput,
Worker & worker,
BuildMode buildMode)
: Goal(worker, haveDerivation()) : Goal(worker, haveDerivation())
, drvPath(drvPath) , drvPath(drvPath)
, wantedOutput(wantedOutput) , wantedOutput(wantedOutput)
, initialOutput{
.wanted = true,
.outputHash = Hash::dummy, // will be updated
.known = {},
}
, buildMode(buildMode) , buildMode(buildMode)
{ {
this->drv = std::make_unique<Derivation>(drv); this->drv = std::make_unique<Derivation>(drv);
@ -125,9 +126,10 @@ Goal::Co DerivationGoal::haveDerivation()
auto outputHashes = staticOutputHashes(worker.evalStore, *drv); auto outputHashes = staticOutputHashes(worker.evalStore, *drv);
for (auto & [outputName, outputHash] : outputHashes) { for (auto & [outputName, outputHash] : outputHashes) {
InitialOutput v{ if (outputName != wantedOutput)
.wanted = true, // Will be refined later continue;
.outputHash = outputHash};
InitialOutput v{.wanted = true, .outputHash = outputHash};
/* TODO we might want to also allow randomizing the paths /* TODO we might want to also allow randomizing the paths
for regular CA derivations, e.g. for sake of checking for regular CA derivations, e.g. for sake of checking
@ -139,10 +141,8 @@ Goal::Co DerivationGoal::haveDerivation()
}; };
} }
initialOutputs.insert({ initialOutput = std::move(v);
outputName, break;
std::move(v),
});
} }
if (impure) { if (impure) {
@ -167,21 +167,18 @@ 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 (!initialOutput.known)
if (!status.wanted) waitees.insert(upcast_goal(worker.makeDrvOutputSubstitutionGoal(
continue; DrvOutput{initialOutput.outputHash, wantedOutput}, buildMode == bmRepair ? Repair : NoRepair)));
if (!status.known) else {
waitees.insert(upcast_goal(worker.makeDrvOutputSubstitutionGoal( auto * cap = getDerivationCA(*drv);
DrvOutput{status.outputHash, outputName}, buildMode == bmRepair ? Repair : NoRepair))); waitees.insert(upcast_goal(worker.makePathSubstitutionGoal(
else { initialOutput.known->path,
auto * cap = getDerivationCA(*drv); buildMode == bmRepair ? Repair : NoRepair,
waitees.insert(upcast_goal(worker.makePathSubstitutionGoal( cap ? std::optional{*cap} : std::nullopt)));
status.known->path,
buildMode == bmRepair ? Repair : NoRepair,
cap ? std::optional{*cap} : std::nullopt)));
}
} }
}
co_await await(std::move(waitees)); co_await await(std::move(waitees));
@ -317,7 +314,6 @@ std::pair<bool, SingleDrvOutputs> DerivationGoal::checkPathValidity()
return {false, {}}; return {false, {}};
bool checkHash = buildMode == bmRepair; bool checkHash = buildMode == bmRepair;
StringSet wantedOutputsLeft{wantedOutput};
SingleDrvOutputs validOutputs; SingleDrvOutputs validOutputs;
auto partialDerivationOutputMap = [&] { auto partialDerivationOutputMap = [&] {
@ -333,17 +329,10 @@ std::pair<bool, SingleDrvOutputs> DerivationGoal::checkPathValidity()
return res; return res;
}(); }();
for (auto & i : partialDerivationOutputMap) { if (auto * mpath = get(partialDerivationOutputMap, wantedOutput)) {
auto initialOutput = get(initialOutputs, i.first); auto & info = initialOutput;
if (!initialOutput) if (*mpath) {
// this is an invalid output, gets caught with (!wantedOutputsLeft.empty()) auto & outputPath = **mpath;
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 = { info.known = {
.path = outputPath, .path = outputPath,
.status = !worker.store.isValidPath(outputPath) ? PathStatus::Absent .status = !worker.store.isValidPath(outputPath) ? PathStatus::Absent
@ -351,7 +340,7 @@ std::pair<bool, SingleDrvOutputs> DerivationGoal::checkPathValidity()
: PathStatus::Corrupt, : PathStatus::Corrupt,
}; };
} }
auto drvOutput = DrvOutput{info.outputHash, i.first}; auto drvOutput = DrvOutput{info.outputHash, wantedOutput};
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
if (auto real = worker.store.queryRealisation(drvOutput)) { if (auto real = worker.store.queryRealisation(drvOutput)) {
info.known = { info.known = {
@ -371,25 +360,19 @@ std::pair<bool, SingleDrvOutputs> DerivationGoal::checkPathValidity()
} }
} }
if (info.known && info.known->isValid()) if (info.known && info.known->isValid())
validOutputs.emplace(i.first, Realisation{drvOutput, info.known->path}); validOutputs.emplace(wantedOutput, Realisation{drvOutput, info.known->path});
} else {
// If we requested all the outputs, we are always fine.
// If we requested specific elements, the loop above removes all the valid
// ones, so any that are left must be invalid.
throw Error(
"derivation '%s' does not have wanted outputs '%s'", worker.store.printStorePath(drvPath), wantedOutput);
} }
// If we requested all the outputs, we are always fine.
// If we requested specific elements, the loop above removes all the valid
// ones, so any that are left must be invalid.
if (!wantedOutputsLeft.empty())
throw Error(
"derivation '%s' does not have wanted outputs %s",
worker.store.printStorePath(drvPath),
concatStringsSep(", ", quoteStrings(wantedOutputsLeft)));
bool allValid = true; bool allValid = true;
for (auto & [_, status] : initialOutputs) { {
if (!status.wanted) if (!initialOutput.known || !initialOutput.known->isValid()) {
continue;
if (!status.known || !status.known->isValid()) {
allValid = false; allValid = false;
break;
} }
} }

View file

@ -74,7 +74,7 @@ private:
* The remainder is state held during the build. * The remainder is state held during the build.
*/ */
std::map<std::string, InitialOutput> initialOutputs; InitialOutput initialOutput;
BuildMode buildMode; BuildMode buildMode;
@ -86,7 +86,7 @@ private:
Co haveDerivation(); Co haveDerivation();
/** /**
* Update 'initialOutputs' to determine the current status of the * Update 'initialOutput' to determine the current status of the
* outputs of the derivation. Also returns a Boolean denoting * outputs of the derivation. Also returns a Boolean denoting
* whether all outputs are valid and non-corrupt, and a * whether all outputs are valid and non-corrupt, and a
* 'SingleDrvOutputs' structure containing the valid outputs. * 'SingleDrvOutputs' structure containing the valid outputs.