mirror of
https://github.com/NixOS/nix.git
synced 2025-12-14 04:51:05 +01:00
Split out UnkeyedRealisation from Realisation
Realisations are conceptually key-value pairs, mapping `DrvOutputs` (the key) to information about that derivation output. This separate the value type, which will be useful in maps, etc., where we don't want to denormalize by including the key twice. This matches similar changes for existing types: | keyed | unkeyed | |--------------------|------------------------| | `ValidPathInfo` | `UnkeyedValidPathInfo` | | `KeyedBuildResult` | `BuildResult` | | `Realisation` | `UnkeyedRealisation` |
This commit is contained in:
parent
28adcfda32
commit
e06968ec25
28 changed files with 363 additions and 251 deletions
|
|
@ -1092,13 +1092,22 @@ DerivationBuildingGoal::checkPathValidity(std::map<std::string, InitialOutput> &
|
|||
// without the `ca-derivations` experimental flag).
|
||||
worker.store.registerDrvOutput(
|
||||
Realisation{
|
||||
{
|
||||
.outPath = info.known->path,
|
||||
},
|
||||
drvOutput,
|
||||
info.known->path,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (info.known && info.known->isValid())
|
||||
validOutputs.emplace(i.first, Realisation{drvOutput, info.known->path});
|
||||
validOutputs.emplace(
|
||||
i.first,
|
||||
Realisation{
|
||||
{
|
||||
.outPath = info.known->path,
|
||||
},
|
||||
drvOutput,
|
||||
});
|
||||
}
|
||||
|
||||
bool allValid = true;
|
||||
|
|
|
|||
|
|
@ -190,13 +190,17 @@ Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
|
|||
auto realisation = [&] {
|
||||
auto take1 = get(success.builtOutputs, wantedOutput);
|
||||
if (take1)
|
||||
return *take1;
|
||||
return static_cast<UnkeyedRealisation>(*take1);
|
||||
|
||||
/* The above `get` should work. But stateful tracking of
|
||||
outputs in resolvedResult, this can get out of sync with the
|
||||
store, which is our actual source of truth. For now we just
|
||||
check the store directly if it fails. */
|
||||
auto take2 = worker.evalStore.queryRealisation(DrvOutput{*resolvedHash, wantedOutput});
|
||||
auto take2 = worker.evalStore.queryRealisation(
|
||||
DrvOutput{
|
||||
.drvHash = *resolvedHash,
|
||||
.outputName = wantedOutput,
|
||||
});
|
||||
if (take2)
|
||||
return *take2;
|
||||
|
||||
|
|
@ -207,8 +211,12 @@ Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
|
|||
}();
|
||||
|
||||
if (!drv->type().isImpure()) {
|
||||
auto newRealisation = realisation;
|
||||
newRealisation.id = DrvOutput{*outputHash, wantedOutput};
|
||||
Realisation newRealisation{
|
||||
realisation,
|
||||
{
|
||||
.drvHash = *outputHash,
|
||||
.outputName = wantedOutput,
|
||||
}};
|
||||
newRealisation.signatures.clear();
|
||||
if (!drv->type().isFixed()) {
|
||||
auto & drvStore = worker.evalStore.isValidPath(drvPath) ? worker.evalStore : worker.store;
|
||||
|
|
@ -258,7 +266,16 @@ Goal::Co DerivationGoal::haveDerivation(bool storeDerivation)
|
|||
/* 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. */
|
||||
success.builtOutputs = {{wantedOutput, assertPathValidity()}};
|
||||
success.builtOutputs = {{
|
||||
wantedOutput,
|
||||
{
|
||||
assertPathValidity(),
|
||||
{
|
||||
.drvHash = outputHash,
|
||||
.outputName = wantedOutput,
|
||||
},
|
||||
},
|
||||
}};
|
||||
} else {
|
||||
/* Otherwise the builder will give us info for out output, but
|
||||
also for other outputs. Filter down to just our output so as
|
||||
|
|
@ -373,18 +390,20 @@ Goal::Co DerivationGoal::repairClosure()
|
|||
co_return doneSuccess(BuildResult::Success::AlreadyValid, assertPathValidity());
|
||||
}
|
||||
|
||||
std::optional<std::pair<Realisation, PathStatus>> DerivationGoal::checkPathValidity()
|
||||
std::optional<std::pair<UnkeyedRealisation, PathStatus>> DerivationGoal::checkPathValidity()
|
||||
{
|
||||
if (drv->type().isImpure())
|
||||
return std::nullopt;
|
||||
|
||||
auto drvOutput = DrvOutput{outputHash, wantedOutput};
|
||||
|
||||
std::optional<Realisation> mRealisation;
|
||||
std::optional<UnkeyedRealisation> mRealisation;
|
||||
|
||||
if (auto * mOutput = get(drv->outputs, wantedOutput)) {
|
||||
if (auto mPath = mOutput->path(worker.store, drv->name, wantedOutput)) {
|
||||
mRealisation = Realisation{drvOutput, std::move(*mPath)};
|
||||
mRealisation = UnkeyedRealisation{
|
||||
.outPath = std::move(*mPath),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
throw Error(
|
||||
|
|
@ -412,7 +431,14 @@ std::optional<std::pair<Realisation, PathStatus>> DerivationGoal::checkPathValid
|
|||
// derivation, and the output path is valid, but we don't have
|
||||
// its realisation stored (probably because it has been built
|
||||
// without the `ca-derivations` experimental flag).
|
||||
worker.store.registerDrvOutput(*mRealisation);
|
||||
worker.store.registerDrvOutput(
|
||||
Realisation{
|
||||
*mRealisation,
|
||||
{
|
||||
.drvHash = outputHash,
|
||||
.outputName = wantedOutput,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {{*mRealisation, status}};
|
||||
|
|
@ -420,7 +446,7 @@ std::optional<std::pair<Realisation, PathStatus>> DerivationGoal::checkPathValid
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
Realisation DerivationGoal::assertPathValidity()
|
||||
UnkeyedRealisation DerivationGoal::assertPathValidity()
|
||||
{
|
||||
auto checkResult = checkPathValidity();
|
||||
if (!(checkResult && checkResult->second == PathStatus::Valid))
|
||||
|
|
@ -428,11 +454,20 @@ Realisation DerivationGoal::assertPathValidity()
|
|||
return checkResult->first;
|
||||
}
|
||||
|
||||
Goal::Done DerivationGoal::doneSuccess(BuildResult::Success::Status status, Realisation builtOutput)
|
||||
Goal::Done DerivationGoal::doneSuccess(BuildResult::Success::Status status, UnkeyedRealisation builtOutput)
|
||||
{
|
||||
buildResult.inner = BuildResult::Success{
|
||||
.status = status,
|
||||
.builtOutputs = {{wantedOutput, std::move(builtOutput)}},
|
||||
.builtOutputs = {{
|
||||
wantedOutput,
|
||||
{
|
||||
std::move(builtOutput),
|
||||
DrvOutput{
|
||||
.drvHash = outputHash,
|
||||
.outputName = wantedOutput,
|
||||
},
|
||||
},
|
||||
}},
|
||||
};
|
||||
|
||||
mcExpectedBuilds.reset();
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ Goal::Co DrvOutputSubstitutionGoal::init()
|
|||
outPipe->createAsyncPipe(worker.ioport.get());
|
||||
#endif
|
||||
|
||||
auto promise = std::make_shared<std::promise<std::shared_ptr<const Realisation>>>();
|
||||
auto promise = std::make_shared<std::promise<std::shared_ptr<const UnkeyedRealisation>>>();
|
||||
|
||||
sub->queryRealisation(
|
||||
id, {[outPipe(outPipe), promise(promise)](std::future<std::shared_ptr<const Realisation>> res) {
|
||||
id, {[outPipe(outPipe), promise(promise)](std::future<std::shared_ptr<const UnkeyedRealisation>> res) {
|
||||
try {
|
||||
Finally updateStats([&]() { outPipe->writeSide.close(); });
|
||||
promise->set_value(res.get());
|
||||
|
|
@ -75,7 +75,7 @@ Goal::Co DrvOutputSubstitutionGoal::init()
|
|||
* The realisation corresponding to the given output id.
|
||||
* Will be filled once we can get it.
|
||||
*/
|
||||
std::shared_ptr<const Realisation> outputInfo;
|
||||
std::shared_ptr<const UnkeyedRealisation> outputInfo;
|
||||
|
||||
try {
|
||||
outputInfo = promise->get_future().get();
|
||||
|
|
@ -132,7 +132,7 @@ Goal::Co DrvOutputSubstitutionGoal::init()
|
|||
}
|
||||
|
||||
Goal::Co DrvOutputSubstitutionGoal::realisationFetched(
|
||||
Goals waitees, std::shared_ptr<const Realisation> outputInfo, nix::ref<nix::Store> sub)
|
||||
Goals waitees, std::shared_ptr<const UnkeyedRealisation> outputInfo, nix::ref<nix::Store> sub)
|
||||
{
|
||||
waitees.insert(worker.makePathSubstitutionGoal(outputInfo->outPath));
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ Goal::Co DrvOutputSubstitutionGoal::realisationFetched(
|
|||
co_return amDone(nrNoSubstituters > 0 ? ecNoSubstituters : ecFailed);
|
||||
}
|
||||
|
||||
worker.store.registerDrvOutput(*outputInfo);
|
||||
worker.store.registerDrvOutput({*outputInfo, id});
|
||||
|
||||
trace("finished");
|
||||
co_return amDone(ecSuccess);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue