mirror of
https://github.com/NixOS/nix
synced 2025-06-28 22:01:15 +02:00
WIP rework goals
This commit is contained in:
parent
d80d68034c
commit
7b01c8b8cd
14 changed files with 498 additions and 98 deletions
|
@ -3,7 +3,7 @@
|
|||
#include "nix/store/build/worker.hh"
|
||||
#include "nix/store/build/substitution-goal.hh"
|
||||
#include "nix/util/callback.hh"
|
||||
#include "nix/store/store-open.hh"
|
||||
#include "nix/store/build/build-trace-goal.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
@ -20,101 +20,32 @@ Goal::Co DrvOutputSubstitutionGoal::init()
|
|||
{
|
||||
trace("init");
|
||||
|
||||
/* If the derivation already exists, we’re done */
|
||||
if (worker.store.queryRealisation(id)) {
|
||||
co_return amDone(ecSuccess);
|
||||
auto goal0 = worker.makeBuildTraceGoal({
|
||||
makeConstantStorePathRef(id.drvPath),
|
||||
id.outputName,
|
||||
});
|
||||
co_await await(Goals{upcast_goal(goal0)});
|
||||
|
||||
trace("output path substituted");
|
||||
|
||||
if (nrFailed > 0) {
|
||||
debug("The output path of the derivation output '%s' could not be substituted", id.render(worker.store));
|
||||
co_return amDone(nrNoSubstituters > 0 ? ecNoSubstituters : ecFailed);
|
||||
}
|
||||
|
||||
auto subs = settings.useSubstitutes ? getDefaultSubstituters() : std::list<ref<Store>>();
|
||||
auto goal1 = worker.makePathSubstitutionGoal(goal0->outputInfo->outPath);
|
||||
goal0.reset();
|
||||
|
||||
bool substituterFailed = false;
|
||||
|
||||
for (const auto & sub : subs) {
|
||||
trace("trying next substituter");
|
||||
|
||||
/* The callback of the curl download below can outlive `this` (if
|
||||
some other error occurs), so it must not touch `this`. So put
|
||||
the shared state in a separate refcounted object. */
|
||||
auto outPipe = std::make_shared<MuxablePipe>();
|
||||
#ifndef _WIN32
|
||||
outPipe->create();
|
||||
#else
|
||||
outPipe->createAsyncPipe(worker.ioport.get());
|
||||
#endif
|
||||
|
||||
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 UnkeyedRealisation>> res) {
|
||||
try {
|
||||
Finally updateStats([&]() { outPipe->writeSide.close(); });
|
||||
promise->set_value(res.get());
|
||||
} catch (...) {
|
||||
promise->set_exception(std::current_exception());
|
||||
}
|
||||
}});
|
||||
|
||||
worker.childStarted(
|
||||
shared_from_this(),
|
||||
{
|
||||
#ifndef _WIN32
|
||||
outPipe->readSide.get()
|
||||
#else
|
||||
&*outPipe
|
||||
#endif
|
||||
},
|
||||
true,
|
||||
false);
|
||||
|
||||
co_await Suspend{};
|
||||
|
||||
worker.childTerminated(this);
|
||||
|
||||
try {
|
||||
outputInfo = promise->get_future().get();
|
||||
} catch (std::exception & e) {
|
||||
printError(e.what());
|
||||
substituterFailed = true;
|
||||
}
|
||||
|
||||
if (!outputInfo)
|
||||
continue;
|
||||
|
||||
co_await await(Goals{worker.makePathSubstitutionGoal(outputInfo->outPath)});
|
||||
|
||||
trace("output path substituted");
|
||||
|
||||
if (nrFailed > 0) {
|
||||
debug("The output path of the derivation output '%s' could not be substituted", id.render(worker.store));
|
||||
co_return amDone(nrNoSubstituters > 0 ? ecNoSubstituters : ecFailed);
|
||||
}
|
||||
|
||||
worker.store.registerDrvOutput({*outputInfo, id});
|
||||
|
||||
trace("finished");
|
||||
co_return amDone(ecSuccess);
|
||||
}
|
||||
|
||||
/* None left. Terminate this goal and let someone else deal
|
||||
with it. */
|
||||
debug("derivation output '%s' is required, but there is no substituter that can provide it", id.render(worker.store));
|
||||
|
||||
if (substituterFailed) {
|
||||
worker.failedSubstitutions++;
|
||||
worker.updateProgress();
|
||||
}
|
||||
|
||||
/* Hack: don't indicate failure if there were no substituters.
|
||||
In that case the calling derivation should just do a
|
||||
build. */
|
||||
co_return amDone(substituterFailed ? ecFailed : ecNoSubstituters);
|
||||
goal1->preserveException = true;
|
||||
co_await await(Goals{upcast_goal(goal1)});
|
||||
co_return amDone(goal1->exitCode, goal1->ex);
|
||||
}
|
||||
|
||||
std::string DrvOutputSubstitutionGoal::key()
|
||||
{
|
||||
/* "a$" ensures substitution goals happen before derivation
|
||||
goals. */
|
||||
return "a$" + std::string(id.render(worker.store));
|
||||
return "b$" + std::string(id.render(worker.store));
|
||||
}
|
||||
|
||||
void DrvOutputSubstitutionGoal::handleEOF(Descriptor fd)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue