forked from lix-project/lix
Fix tests on systems with a non-master git defaultBranch #1
|
@ -13,8 +13,11 @@
|
||||||
|
|
||||||
#include <boost/outcome/try.hpp>
|
#include <boost/outcome/try.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <kj/array.h>
|
||||||
#include <kj/async-unix.h>
|
#include <kj/async-unix.h>
|
||||||
|
#include <kj/async.h>
|
||||||
#include <kj/debug.h>
|
#include <kj/debug.h>
|
||||||
|
#include <kj/vector.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
@ -173,7 +176,7 @@ try {
|
||||||
|
|
||||||
|
|
||||||
state = &DerivationGoal::loadDerivation;
|
state = &DerivationGoal::loadDerivation;
|
||||||
return {WaitForGoals{{worker.goalFactory().makePathSubstitutionGoal(drvPath)}}};
|
return waitForGoals(worker.goalFactory().makePathSubstitutionGoal(drvPath));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return {std::current_exception()};
|
return {std::current_exception()};
|
||||||
}
|
}
|
||||||
|
@ -272,13 +275,13 @@ try {
|
||||||
/* 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. */
|
||||||
WaitForGoals result;
|
kj::Vector<std::pair<GoalPtr, kj::Promise<void>>> dependencies;
|
||||||
if (settings.useSubstitutes) {
|
if (settings.useSubstitutes) {
|
||||||
if (parsedDrv->substitutesAllowed()) {
|
if (parsedDrv->substitutesAllowed()) {
|
||||||
for (auto & [outputName, status] : initialOutputs) {
|
for (auto & [outputName, status] : initialOutputs) {
|
||||||
if (!status.wanted) continue;
|
if (!status.wanted) continue;
|
||||||
if (!status.known)
|
if (!status.known)
|
||||||
result.goals.insert(
|
dependencies.add(
|
||||||
worker.goalFactory().makeDrvOutputSubstitutionGoal(
|
worker.goalFactory().makeDrvOutputSubstitutionGoal(
|
||||||
DrvOutput{status.outputHash, outputName},
|
DrvOutput{status.outputHash, outputName},
|
||||||
buildMode == bmRepair ? Repair : NoRepair
|
buildMode == bmRepair ? Repair : NoRepair
|
||||||
|
@ -286,7 +289,7 @@ try {
|
||||||
);
|
);
|
||||||
else {
|
else {
|
||||||
auto * cap = getDerivationCA(*drv);
|
auto * cap = getDerivationCA(*drv);
|
||||||
result.goals.insert(worker.goalFactory().makePathSubstitutionGoal(
|
dependencies.add(worker.goalFactory().makePathSubstitutionGoal(
|
||||||
status.known->path,
|
status.known->path,
|
||||||
buildMode == bmRepair ? Repair : NoRepair,
|
buildMode == bmRepair ? Repair : NoRepair,
|
||||||
cap ? std::optional { *cap } : std::nullopt));
|
cap ? std::optional { *cap } : std::nullopt));
|
||||||
|
@ -297,11 +300,11 @@ try {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.goals.empty()) { /* to prevent hang (no wake-up event) */
|
if (dependencies.empty()) { /* to prevent hang (no wake-up event) */
|
||||||
return outputsSubstitutionTried(inBuildSlot);
|
return outputsSubstitutionTried(inBuildSlot);
|
||||||
} else {
|
} else {
|
||||||
state = &DerivationGoal::outputsSubstitutionTried;
|
state = &DerivationGoal::outputsSubstitutionTried;
|
||||||
return {std::move(result)};
|
return waitForGoals(dependencies.releaseAsArray());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return {std::current_exception()};
|
return {std::current_exception()};
|
||||||
|
@ -383,7 +386,7 @@ try {
|
||||||
produced using a substitute. So we have to build instead. */
|
produced using a substitute. So we have to build instead. */
|
||||||
kj::Promise<Result<Goal::WorkResult>> DerivationGoal::gaveUpOnSubstitution(bool inBuildSlot) noexcept
|
kj::Promise<Result<Goal::WorkResult>> DerivationGoal::gaveUpOnSubstitution(bool inBuildSlot) noexcept
|
||||||
try {
|
try {
|
||||||
WaitForGoals result;
|
kj::Vector<std::pair<GoalPtr, kj::Promise<void>>> dependencies;
|
||||||
|
|
||||||
/* At this point we are building all outputs, so if more are wanted there
|
/* At this point we are building all outputs, so if more are wanted there
|
||||||
is no need to restart. */
|
is no need to restart. */
|
||||||
|
@ -396,7 +399,7 @@ try {
|
||||||
|
|
||||||
addWaiteeDerivedPath = [&](ref<SingleDerivedPath> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
|
addWaiteeDerivedPath = [&](ref<SingleDerivedPath> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
|
||||||
if (!inputNode.value.empty())
|
if (!inputNode.value.empty())
|
||||||
result.goals.insert(worker.goalFactory().makeGoal(
|
dependencies.add(worker.goalFactory().makeGoal(
|
||||||
DerivedPath::Built {
|
DerivedPath::Built {
|
||||||
.drvPath = inputDrv,
|
.drvPath = inputDrv,
|
||||||
.outputs = inputNode.value,
|
.outputs = inputNode.value,
|
||||||
|
@ -441,14 +444,14 @@ try {
|
||||||
if (!settings.useSubstitutes)
|
if (!settings.useSubstitutes)
|
||||||
throw Error("dependency '%s' of '%s' does not exist, and substitution is disabled",
|
throw Error("dependency '%s' of '%s' does not exist, and substitution is disabled",
|
||||||
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
||||||
result.goals.insert(worker.goalFactory().makePathSubstitutionGoal(i));
|
dependencies.add(worker.goalFactory().makePathSubstitutionGoal(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.goals.empty()) {/* to prevent hang (no wake-up event) */
|
if (dependencies.empty()) {/* to prevent hang (no wake-up event) */
|
||||||
return inputsRealised(inBuildSlot);
|
return inputsRealised(inBuildSlot);
|
||||||
} else {
|
} else {
|
||||||
state = &DerivationGoal::inputsRealised;
|
state = &DerivationGoal::inputsRealised;
|
||||||
return {result};
|
return waitForGoals(dependencies.releaseAsArray());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return {std::current_exception()};
|
return {std::current_exception()};
|
||||||
|
@ -491,7 +494,7 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check each path (slow!). */
|
/* Check each path (slow!). */
|
||||||
WaitForGoals result;
|
kj::Vector<std::pair<GoalPtr, kj::Promise<void>>> dependencies;
|
||||||
for (auto & i : outputClosure) {
|
for (auto & i : outputClosure) {
|
||||||
if (worker.pathContentsGood(i)) continue;
|
if (worker.pathContentsGood(i)) continue;
|
||||||
printError(
|
printError(
|
||||||
|
@ -499,9 +502,9 @@ try {
|
||||||
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
worker.store.printStorePath(i), worker.store.printStorePath(drvPath));
|
||||||
auto drvPath2 = outputsToDrv.find(i);
|
auto drvPath2 = outputsToDrv.find(i);
|
||||||
if (drvPath2 == outputsToDrv.end())
|
if (drvPath2 == outputsToDrv.end())
|
||||||
result.goals.insert(worker.goalFactory().makePathSubstitutionGoal(i, Repair));
|
dependencies.add(worker.goalFactory().makePathSubstitutionGoal(i, Repair));
|
||||||
else
|
else
|
||||||
result.goals.insert(worker.goalFactory().makeGoal(
|
dependencies.add(worker.goalFactory().makeGoal(
|
||||||
DerivedPath::Built {
|
DerivedPath::Built {
|
||||||
.drvPath = makeConstantStorePathRef(drvPath2->second),
|
.drvPath = makeConstantStorePathRef(drvPath2->second),
|
||||||
.outputs = OutputsSpec::All { },
|
.outputs = OutputsSpec::All { },
|
||||||
|
@ -509,12 +512,12 @@ try {
|
||||||
bmRepair));
|
bmRepair));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.goals.empty()) {
|
if (dependencies.empty()) {
|
||||||
return {done(BuildResult::AlreadyValid, assertPathValidity())};
|
return {done(BuildResult::AlreadyValid, assertPathValidity())};
|
||||||
}
|
}
|
||||||
|
|
||||||
state = &DerivationGoal::closureRepaired;
|
state = &DerivationGoal::closureRepaired;
|
||||||
return {result};
|
return waitForGoals(dependencies.releaseAsArray());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return {std::current_exception()};
|
return {std::current_exception()};
|
||||||
}
|
}
|
||||||
|
@ -614,11 +617,12 @@ try {
|
||||||
worker.store.printStorePath(pathResolved),
|
worker.store.printStorePath(pathResolved),
|
||||||
});
|
});
|
||||||
|
|
||||||
resolvedDrvGoal = worker.goalFactory().makeDerivationGoal(
|
auto dependency = worker.goalFactory().makeDerivationGoal(
|
||||||
pathResolved, wantedOutputs, buildMode);
|
pathResolved, wantedOutputs, buildMode);
|
||||||
|
resolvedDrvGoal = dependency.first;
|
||||||
|
|
||||||
state = &DerivationGoal::resolvedFinished;
|
state = &DerivationGoal::resolvedFinished;
|
||||||
return {WaitForGoals{{resolvedDrvGoal}}};
|
return waitForGoals(std::move(dependency));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<void(const StorePath &, const DerivedPathMap<StringSet>::ChildNode &)> accumInputPaths;
|
std::function<void(const StorePath &, const DerivedPathMap<StringSet>::ChildNode &)> accumInputPaths;
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include "worker.hh"
|
#include "worker.hh"
|
||||||
#include "substitution-goal.hh"
|
#include "substitution-goal.hh"
|
||||||
#include "signals.hh"
|
#include "signals.hh"
|
||||||
|
#include <kj/array.h>
|
||||||
|
#include <kj/async.h>
|
||||||
|
#include <kj/vector.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -106,7 +109,7 @@ try {
|
||||||
return tryNext(inBuildSlot);
|
return tryNext(inBuildSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForGoals result;
|
kj::Vector<std::pair<GoalPtr, kj::Promise<void>>> dependencies;
|
||||||
for (const auto & [depId, depPath] : outputInfo->dependentRealisations) {
|
for (const auto & [depId, depPath] : outputInfo->dependentRealisations) {
|
||||||
if (depId != id) {
|
if (depId != id) {
|
||||||
if (auto localOutputInfo = worker.store.queryRealisation(depId);
|
if (auto localOutputInfo = worker.store.queryRealisation(depId);
|
||||||
|
@ -122,17 +125,17 @@ try {
|
||||||
);
|
);
|
||||||
return tryNext(inBuildSlot);
|
return tryNext(inBuildSlot);
|
||||||
}
|
}
|
||||||
result.goals.insert(worker.goalFactory().makeDrvOutputSubstitutionGoal(depId));
|
dependencies.add(worker.goalFactory().makeDrvOutputSubstitutionGoal(depId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.goals.insert(worker.goalFactory().makePathSubstitutionGoal(outputInfo->outPath));
|
dependencies.add(worker.goalFactory().makePathSubstitutionGoal(outputInfo->outPath));
|
||||||
|
|
||||||
if (result.goals.empty()) {
|
if (dependencies.empty()) {
|
||||||
return outPathValid(inBuildSlot);
|
return outPathValid(inBuildSlot);
|
||||||
} else {
|
} else {
|
||||||
state = &DrvOutputSubstitutionGoal::outPathValid;
|
state = &DrvOutputSubstitutionGoal::outPathValid;
|
||||||
return {std::move(result)};
|
return waitForGoals(dependencies.releaseAsArray());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return {std::current_exception()};
|
return {std::current_exception()};
|
||||||
|
|
|
@ -17,9 +17,9 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
|
||||||
Worker worker(*this, evalStore ? *evalStore : *this, aio);
|
Worker worker(*this, evalStore ? *evalStore : *this, aio);
|
||||||
|
|
||||||
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
||||||
Goals goals;
|
Worker::Targets goals;
|
||||||
for (auto & br : reqs)
|
for (auto & br : reqs)
|
||||||
goals.insert(gf.makeGoal(br, buildMode));
|
goals.emplace(gf.makeGoal(br, buildMode));
|
||||||
return goals;
|
return goals;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -60,11 +60,11 @@ std::vector<KeyedBuildResult> Store::buildPathsWithResults(
|
||||||
std::vector<std::pair<const DerivedPath &, GoalPtr>> state;
|
std::vector<std::pair<const DerivedPath &, GoalPtr>> state;
|
||||||
|
|
||||||
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
||||||
Goals goals;
|
Worker::Targets goals;
|
||||||
for (const auto & req : reqs) {
|
for (const auto & req : reqs) {
|
||||||
auto goal = gf.makeGoal(req, buildMode);
|
auto goal = gf.makeGoal(req, buildMode);
|
||||||
goals.insert(goal);
|
state.push_back({req, goal.first});
|
||||||
state.push_back({req, goal});
|
goals.emplace(std::move(goal));
|
||||||
}
|
}
|
||||||
return goals;
|
return goals;
|
||||||
});
|
});
|
||||||
|
@ -84,8 +84,10 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat
|
||||||
Worker worker(*this, *this, aio);
|
Worker worker(*this, *this, aio);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto goals = runWorker(worker, [&](GoalFactory & gf) -> Goals {
|
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
||||||
return Goals{gf.makeBasicDerivationGoal(drvPath, drv, OutputsSpec::All{}, buildMode)};
|
Worker::Targets goals;
|
||||||
|
goals.emplace(gf.makeBasicDerivationGoal(drvPath, drv, OutputsSpec::All{}, buildMode));
|
||||||
|
return goals;
|
||||||
});
|
});
|
||||||
auto goal = *goals.begin();
|
auto goal = *goals.begin();
|
||||||
return goal->buildResult.restrictTo(DerivedPath::Built {
|
return goal->buildResult.restrictTo(DerivedPath::Built {
|
||||||
|
@ -110,7 +112,9 @@ void Store::ensurePath(const StorePath & path)
|
||||||
Worker worker(*this, *this, aio);
|
Worker worker(*this, *this, aio);
|
||||||
|
|
||||||
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
||||||
return Goals{gf.makePathSubstitutionGoal(path)};
|
Worker::Targets goals;
|
||||||
|
goals.emplace(gf.makePathSubstitutionGoal(path));
|
||||||
|
return goals;
|
||||||
});
|
});
|
||||||
auto goal = *goals.begin();
|
auto goal = *goals.begin();
|
||||||
|
|
||||||
|
@ -130,7 +134,9 @@ void Store::repairPath(const StorePath & path)
|
||||||
Worker worker(*this, *this, aio);
|
Worker worker(*this, *this, aio);
|
||||||
|
|
||||||
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
auto goals = runWorker(worker, [&](GoalFactory & gf) {
|
||||||
return Goals{gf.makePathSubstitutionGoal(path, Repair)};
|
Worker::Targets goals;
|
||||||
|
goals.emplace(gf.makePathSubstitutionGoal(path, Repair));
|
||||||
|
return goals;
|
||||||
});
|
});
|
||||||
auto goal = *goals.begin();
|
auto goal = *goals.begin();
|
||||||
|
|
||||||
|
@ -140,14 +146,16 @@ void Store::repairPath(const StorePath & path)
|
||||||
auto info = queryPathInfo(path);
|
auto info = queryPathInfo(path);
|
||||||
if (info->deriver && isValidPath(*info->deriver)) {
|
if (info->deriver && isValidPath(*info->deriver)) {
|
||||||
worker.run([&](GoalFactory & gf) {
|
worker.run([&](GoalFactory & gf) {
|
||||||
return Goals{gf.makeGoal(
|
Worker::Targets goals;
|
||||||
|
goals.emplace(gf.makeGoal(
|
||||||
DerivedPath::Built{
|
DerivedPath::Built{
|
||||||
.drvPath = makeConstantStorePathRef(*info->deriver),
|
.drvPath = makeConstantStorePathRef(*info->deriver),
|
||||||
// FIXME: Should just build the specific output we need.
|
// FIXME: Should just build the specific output we need.
|
||||||
.outputs = OutputsSpec::All{},
|
.outputs = OutputsSpec::All{},
|
||||||
},
|
},
|
||||||
bmRepair
|
bmRepair
|
||||||
)};
|
));
|
||||||
|
return goals;
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
throw Error(worker.failingExitStatus(), "cannot repair path '%s'", printStorePath(path));
|
throw Error(worker.failingExitStatus(), "cannot repair path '%s'", printStorePath(path));
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "goal.hh"
|
#include "goal.hh"
|
||||||
|
#include "async-collect.hh"
|
||||||
#include "worker.hh"
|
#include "worker.hh"
|
||||||
#include <kj/time.h>
|
#include <kj/time.h>
|
||||||
|
|
||||||
|
@ -28,4 +29,32 @@ try {
|
||||||
co_return std::current_exception();
|
co_return std::current_exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kj::Promise<Result<Goal::WorkResult>>
|
||||||
|
Goal::waitForGoals(kj::Array<std::pair<GoalPtr, kj::Promise<void>>> dependencies) noexcept
|
||||||
|
try {
|
||||||
|
auto left = dependencies.size();
|
||||||
|
auto collectDeps = asyncCollect(std::move(dependencies));
|
||||||
|
|
||||||
|
while (auto item = co_await collectDeps.next()) {
|
||||||
|
left--;
|
||||||
|
auto & dep = *item;
|
||||||
|
|
||||||
|
trace(fmt("waitee '%s' done; %d left", dep->name, left));
|
||||||
|
|
||||||
|
if (dep->exitCode != Goal::ecSuccess) ++nrFailed;
|
||||||
|
if (dep->exitCode == Goal::ecNoSubstituters) ++nrNoSubstituters;
|
||||||
|
if (dep->exitCode == Goal::ecIncompleteClosure) ++nrIncompleteClosure;
|
||||||
|
|
||||||
|
waiteeDone(dep);
|
||||||
|
|
||||||
|
if (dep->exitCode == ecFailed && !settings.keepGoing) {
|
||||||
|
co_return result::success(ContinueImmediately{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
co_return result::success(ContinueImmediately{});
|
||||||
|
} catch (...) {
|
||||||
|
co_return result::failure(std::current_exception());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "build-result.hh"
|
#include "build-result.hh"
|
||||||
|
#include <concepts> // IWYU pragma: keep
|
||||||
#include <kj/async.h>
|
#include <kj/async.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -70,17 +71,6 @@ struct Goal
|
||||||
*/
|
*/
|
||||||
const bool isDependency;
|
const bool isDependency;
|
||||||
|
|
||||||
/**
|
|
||||||
* Goals that this goal is waiting for.
|
|
||||||
*/
|
|
||||||
Goals waitees;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Goals waiting for this one to finish. Must use weak pointers
|
|
||||||
* here to prevent cycles.
|
|
||||||
*/
|
|
||||||
WeakGoals waiters;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of goals we are/were waiting for that have failed.
|
* Number of goals we are/were waiting for that have failed.
|
||||||
*/
|
*/
|
||||||
|
@ -113,6 +103,9 @@ struct Goal
|
||||||
*/
|
*/
|
||||||
BuildResult buildResult;
|
BuildResult buildResult;
|
||||||
|
|
||||||
|
// for use by Worker only. will go away once work() is a promise.
|
||||||
|
kj::Own<kj::PromiseFulfiller<void>> notify;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AsyncSemaphore::Token slotToken;
|
AsyncSemaphore::Token slotToken;
|
||||||
|
|
||||||
|
@ -122,9 +115,6 @@ public:
|
||||||
|
|
||||||
struct [[nodiscard]] StillAlive {};
|
struct [[nodiscard]] StillAlive {};
|
||||||
struct [[nodiscard]] ContinueImmediately {};
|
struct [[nodiscard]] ContinueImmediately {};
|
||||||
struct [[nodiscard]] WaitForGoals {
|
|
||||||
Goals goals;
|
|
||||||
};
|
|
||||||
struct [[nodiscard]] WaitForWorld {
|
struct [[nodiscard]] WaitForWorld {
|
||||||
kj::Promise<Outcome<void, Finished>> promise;
|
kj::Promise<Outcome<void, Finished>> promise;
|
||||||
};
|
};
|
||||||
|
@ -141,7 +131,6 @@ public:
|
||||||
struct [[nodiscard]] WorkResult : std::variant<
|
struct [[nodiscard]] WorkResult : std::variant<
|
||||||
StillAlive,
|
StillAlive,
|
||||||
ContinueImmediately,
|
ContinueImmediately,
|
||||||
WaitForGoals,
|
|
||||||
WaitForWorld,
|
WaitForWorld,
|
||||||
Finished>
|
Finished>
|
||||||
{
|
{
|
||||||
|
@ -151,6 +140,15 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
kj::Promise<Result<WorkResult>> waitForAWhile();
|
kj::Promise<Result<WorkResult>> waitForAWhile();
|
||||||
|
kj::Promise<Result<WorkResult>>
|
||||||
|
waitForGoals(kj::Array<std::pair<GoalPtr, kj::Promise<void>>> dependencies) noexcept;
|
||||||
|
|
||||||
|
template<std::derived_from<Goal>... G>
|
||||||
|
kj::Promise<Result<Goal::WorkResult>>
|
||||||
|
waitForGoals(std::pair<std::shared_ptr<G>, kj::Promise<void>>... goals) noexcept
|
||||||
|
{
|
||||||
|
return waitForGoals(kj::arrOf<std::pair<GoalPtr, kj::Promise<void>>>(std::move(goals)...));
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "nar-info.hh"
|
#include "nar-info.hh"
|
||||||
#include "signals.hh"
|
#include "signals.hh"
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
|
#include <kj/array.h>
|
||||||
|
#include <kj/vector.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -160,16 +162,16 @@ try {
|
||||||
|
|
||||||
/* To maintain the closure invariant, we first have to realise the
|
/* To maintain the closure invariant, we first have to realise the
|
||||||
paths referenced by this one. */
|
paths referenced by this one. */
|
||||||
WaitForGoals result;
|
kj::Vector<std::pair<GoalPtr, kj::Promise<void>>> dependencies;
|
||||||
for (auto & i : info->references)
|
for (auto & i : info->references)
|
||||||
if (i != storePath) /* ignore self-references */
|
if (i != storePath) /* ignore self-references */
|
||||||
result.goals.insert(worker.goalFactory().makePathSubstitutionGoal(i));
|
dependencies.add(worker.goalFactory().makePathSubstitutionGoal(i));
|
||||||
|
|
||||||
if (result.goals.empty()) {/* to prevent hang (no wake-up event) */
|
if (dependencies.empty()) {/* to prevent hang (no wake-up event) */
|
||||||
return referencesValid(inBuildSlot);
|
return referencesValid(inBuildSlot);
|
||||||
} else {
|
} else {
|
||||||
state = &PathSubstitutionGoal::referencesValid;
|
state = &PathSubstitutionGoal::referencesValid;
|
||||||
return {std::move(result)};
|
return waitForGoals(dependencies.releaseAsArray());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return {std::current_exception()};
|
return {std::current_exception()};
|
||||||
|
|
|
@ -52,26 +52,28 @@ Worker::~Worker()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<DerivationGoal> Worker::makeDerivationGoalCommon(
|
std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> Worker::makeDerivationGoalCommon(
|
||||||
const StorePath & drvPath,
|
const StorePath & drvPath,
|
||||||
const OutputsSpec & wantedOutputs,
|
const OutputsSpec & wantedOutputs,
|
||||||
std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal)
|
std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal)
|
||||||
{
|
{
|
||||||
std::weak_ptr<DerivationGoal> & goal_weak = derivationGoals[drvPath];
|
auto & goal_weak = derivationGoals[drvPath];
|
||||||
std::shared_ptr<DerivationGoal> goal = goal_weak.lock();
|
std::shared_ptr<DerivationGoal> goal = goal_weak.goal.lock();
|
||||||
if (!goal) {
|
if (!goal) {
|
||||||
goal = mkDrvGoal();
|
goal = mkDrvGoal();
|
||||||
goal_weak = goal;
|
goal->notify = std::move(goal_weak.fulfiller);
|
||||||
|
goal_weak.goal = goal;
|
||||||
wakeUp(goal);
|
wakeUp(goal);
|
||||||
} else {
|
} else {
|
||||||
goal->addWantedOutputs(wantedOutputs);
|
goal->addWantedOutputs(wantedOutputs);
|
||||||
}
|
}
|
||||||
return goal;
|
return {goal, goal_weak.promise->addBranch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<DerivationGoal> Worker::makeDerivationGoal(const StorePath & drvPath,
|
std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> Worker::makeDerivationGoal(
|
||||||
const OutputsSpec & wantedOutputs, BuildMode buildMode)
|
const StorePath & drvPath, const OutputsSpec & wantedOutputs, BuildMode buildMode
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return makeDerivationGoalCommon(
|
return makeDerivationGoalCommon(
|
||||||
drvPath,
|
drvPath,
|
||||||
|
@ -89,8 +91,12 @@ std::shared_ptr<DerivationGoal> Worker::makeDerivationGoal(const StorePath & drv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<DerivationGoal> Worker::makeBasicDerivationGoal(const StorePath & drvPath,
|
std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> Worker::makeBasicDerivationGoal(
|
||||||
const BasicDerivation & drv, const OutputsSpec & wantedOutputs, BuildMode buildMode)
|
const StorePath & drvPath,
|
||||||
|
const BasicDerivation & drv,
|
||||||
|
const OutputsSpec & wantedOutputs,
|
||||||
|
BuildMode buildMode
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return makeDerivationGoalCommon(
|
return makeDerivationGoalCommon(
|
||||||
drvPath,
|
drvPath,
|
||||||
|
@ -108,55 +114,63 @@ std::shared_ptr<DerivationGoal> Worker::makeBasicDerivationGoal(const StorePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<PathSubstitutionGoal> Worker::makePathSubstitutionGoal(const StorePath & path, RepairFlag repair, std::optional<ContentAddress> ca)
|
std::pair<std::shared_ptr<PathSubstitutionGoal>, kj::Promise<void>>
|
||||||
|
Worker::makePathSubstitutionGoal(
|
||||||
|
const StorePath & path, RepairFlag repair, std::optional<ContentAddress> ca
|
||||||
|
)
|
||||||
{
|
{
|
||||||
std::weak_ptr<PathSubstitutionGoal> & goal_weak = substitutionGoals[path];
|
auto & goal_weak = substitutionGoals[path];
|
||||||
auto goal = goal_weak.lock(); // FIXME
|
auto goal = goal_weak.goal.lock(); // FIXME
|
||||||
if (!goal) {
|
if (!goal) {
|
||||||
goal = std::make_shared<PathSubstitutionGoal>(path, *this, running, repair, ca);
|
goal = std::make_shared<PathSubstitutionGoal>(path, *this, running, repair, ca);
|
||||||
goal_weak = goal;
|
goal->notify = std::move(goal_weak.fulfiller);
|
||||||
|
goal_weak.goal = goal;
|
||||||
wakeUp(goal);
|
wakeUp(goal);
|
||||||
}
|
}
|
||||||
return goal;
|
return {goal, goal_weak.promise->addBranch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<DrvOutputSubstitutionGoal> Worker::makeDrvOutputSubstitutionGoal(const DrvOutput& id, RepairFlag repair, std::optional<ContentAddress> ca)
|
std::pair<std::shared_ptr<DrvOutputSubstitutionGoal>, kj::Promise<void>>
|
||||||
|
Worker::makeDrvOutputSubstitutionGoal(
|
||||||
|
const DrvOutput & id, RepairFlag repair, std::optional<ContentAddress> ca
|
||||||
|
)
|
||||||
{
|
{
|
||||||
std::weak_ptr<DrvOutputSubstitutionGoal> & goal_weak = drvOutputSubstitutionGoals[id];
|
auto & goal_weak = drvOutputSubstitutionGoals[id];
|
||||||
auto goal = goal_weak.lock(); // FIXME
|
auto goal = goal_weak.goal.lock(); // FIXME
|
||||||
if (!goal) {
|
if (!goal) {
|
||||||
goal = std::make_shared<DrvOutputSubstitutionGoal>(id, *this, running, repair, ca);
|
goal = std::make_shared<DrvOutputSubstitutionGoal>(id, *this, running, repair, ca);
|
||||||
goal_weak = goal;
|
goal->notify = std::move(goal_weak.fulfiller);
|
||||||
|
goal_weak.goal = goal;
|
||||||
wakeUp(goal);
|
wakeUp(goal);
|
||||||
}
|
}
|
||||||
return goal;
|
return {goal, goal_weak.promise->addBranch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GoalPtr Worker::makeGoal(const DerivedPath & req, BuildMode buildMode)
|
std::pair<GoalPtr, kj::Promise<void>> Worker::makeGoal(const DerivedPath & req, BuildMode buildMode)
|
||||||
{
|
{
|
||||||
return std::visit(overloaded {
|
return std::visit(overloaded {
|
||||||
[&](const DerivedPath::Built & bfd) -> GoalPtr {
|
[&](const DerivedPath::Built & bfd) -> std::pair<GoalPtr, kj::Promise<void>> {
|
||||||
if (auto bop = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath))
|
if (auto bop = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath))
|
||||||
return makeDerivationGoal(bop->path, bfd.outputs, buildMode);
|
return makeDerivationGoal(bop->path, bfd.outputs, buildMode);
|
||||||
else
|
else
|
||||||
throw UnimplementedError("Building dynamic derivations in one shot is not yet implemented.");
|
throw UnimplementedError("Building dynamic derivations in one shot is not yet implemented.");
|
||||||
},
|
},
|
||||||
[&](const DerivedPath::Opaque & bo) -> GoalPtr {
|
[&](const DerivedPath::Opaque & bo) -> std::pair<GoalPtr, kj::Promise<void>> {
|
||||||
return makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair);
|
return makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair);
|
||||||
},
|
},
|
||||||
}, req.raw());
|
}, req.raw());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename K, typename G>
|
template<typename G>
|
||||||
static void removeGoal(std::shared_ptr<G> goal, std::map<K, std::weak_ptr<G>> & goalMap)
|
static void removeGoal(std::shared_ptr<G> goal, auto & goalMap)
|
||||||
{
|
{
|
||||||
/* !!! inefficient */
|
/* !!! inefficient */
|
||||||
for (auto i = goalMap.begin();
|
for (auto i = goalMap.begin();
|
||||||
i != goalMap.end(); )
|
i != goalMap.end(); )
|
||||||
if (i->second.lock() == goal) {
|
if (i->second.goal.lock() == goal) {
|
||||||
auto j = i; ++j;
|
auto j = i; ++j;
|
||||||
goalMap.erase(i);
|
goalMap.erase(i);
|
||||||
i = j;
|
i = j;
|
||||||
|
@ -177,33 +191,8 @@ void Worker::goalFinished(GoalPtr goal, Goal::Finished & f)
|
||||||
hashMismatch |= f.hashMismatch;
|
hashMismatch |= f.hashMismatch;
|
||||||
checkMismatch |= f.checkMismatch;
|
checkMismatch |= f.checkMismatch;
|
||||||
|
|
||||||
for (auto & i : goal->waiters) {
|
|
||||||
if (GoalPtr waiting = i.lock()) {
|
|
||||||
assert(waiting->waitees.count(goal));
|
|
||||||
waiting->waitees.erase(goal);
|
|
||||||
|
|
||||||
waiting->trace(fmt("waitee '%s' done; %d left", goal->name, waiting->waitees.size()));
|
|
||||||
|
|
||||||
if (f.exitCode != Goal::ecSuccess) ++waiting->nrFailed;
|
|
||||||
if (f.exitCode == Goal::ecNoSubstituters) ++waiting->nrNoSubstituters;
|
|
||||||
if (f.exitCode == Goal::ecIncompleteClosure) ++waiting->nrIncompleteClosure;
|
|
||||||
|
|
||||||
if (waiting->waitees.empty() || (f.exitCode == Goal::ecFailed && !settings.keepGoing)) {
|
|
||||||
/* If we failed and keepGoing is not set, we remove all
|
|
||||||
remaining waitees. */
|
|
||||||
for (auto & i : waiting->waitees) {
|
|
||||||
i->waiters.extract(waiting);
|
|
||||||
}
|
|
||||||
waiting->waitees.clear();
|
|
||||||
|
|
||||||
wakeUp(waiting);
|
|
||||||
}
|
|
||||||
|
|
||||||
waiting->waiteeDone(goal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goal->waiters.clear();
|
|
||||||
removeGoal(goal);
|
removeGoal(goal);
|
||||||
|
goal->notify->fulfill();
|
||||||
goal->cleanup();
|
goal->cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,12 +202,6 @@ void Worker::handleWorkResult(GoalPtr goal, Goal::WorkResult how)
|
||||||
overloaded{
|
overloaded{
|
||||||
[&](Goal::StillAlive) {},
|
[&](Goal::StillAlive) {},
|
||||||
[&](Goal::ContinueImmediately) { wakeUp(goal); },
|
[&](Goal::ContinueImmediately) { wakeUp(goal); },
|
||||||
[&](Goal::WaitForGoals & w) {
|
|
||||||
for (auto & dep : w.goals) {
|
|
||||||
goal->waitees.insert(dep);
|
|
||||||
dep->waiters.insert(goal);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[&](Goal::WaitForWorld & w) {
|
[&](Goal::WaitForWorld & w) {
|
||||||
childStarted(goal, w.promise.then([](auto r) -> Result<Goal::WorkResult> {
|
childStarted(goal, w.promise.then([](auto r) -> Result<Goal::WorkResult> {
|
||||||
if (r.has_value()) {
|
if (r.has_value()) {
|
||||||
|
@ -310,7 +293,7 @@ void Worker::updateStatistics()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Goals Worker::run(std::function<Goals (GoalFactory &)> req)
|
std::vector<GoalPtr> Worker::run(std::function<Targets (GoalFactory &)> req)
|
||||||
{
|
{
|
||||||
auto _topGoals = req(goalFactory());
|
auto _topGoals = req(goalFactory());
|
||||||
|
|
||||||
|
@ -320,7 +303,10 @@ Goals Worker::run(std::function<Goals (GoalFactory &)> req)
|
||||||
|
|
||||||
updateStatistics();
|
updateStatistics();
|
||||||
|
|
||||||
topGoals = _topGoals;
|
topGoals.clear();
|
||||||
|
for (auto & [goal, _promise] : _topGoals) {
|
||||||
|
topGoals.insert(goal);
|
||||||
|
}
|
||||||
|
|
||||||
debug("entered goal loop");
|
debug("entered goal loop");
|
||||||
|
|
||||||
|
@ -374,7 +360,11 @@ Goals Worker::run(std::function<Goals (GoalFactory &)> req)
|
||||||
assert(!settings.keepGoing || awake.empty());
|
assert(!settings.keepGoing || awake.empty());
|
||||||
assert(!settings.keepGoing || children.isEmpty());
|
assert(!settings.keepGoing || children.isEmpty());
|
||||||
|
|
||||||
return _topGoals;
|
std::vector<GoalPtr> results;
|
||||||
|
for (auto & [i, _p] : _topGoals) {
|
||||||
|
results.push_back(i);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Worker::waitForInput()
|
void Worker::waitForInput()
|
||||||
|
|
|
@ -28,10 +28,10 @@ struct HookInstance;
|
||||||
class GoalFactory
|
class GoalFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual std::shared_ptr<DerivationGoal> makeDerivationGoal(
|
virtual std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> makeDerivationGoal(
|
||||||
const StorePath & drvPath, const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal
|
const StorePath & drvPath, const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal
|
||||||
) = 0;
|
) = 0;
|
||||||
virtual std::shared_ptr<DerivationGoal> makeBasicDerivationGoal(
|
virtual std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> makeBasicDerivationGoal(
|
||||||
const StorePath & drvPath,
|
const StorePath & drvPath,
|
||||||
const BasicDerivation & drv,
|
const BasicDerivation & drv,
|
||||||
const OutputsSpec & wantedOutputs,
|
const OutputsSpec & wantedOutputs,
|
||||||
|
@ -41,12 +41,14 @@ public:
|
||||||
/**
|
/**
|
||||||
* @ref SubstitutionGoal "substitution goal"
|
* @ref SubstitutionGoal "substitution goal"
|
||||||
*/
|
*/
|
||||||
virtual std::shared_ptr<PathSubstitutionGoal> makePathSubstitutionGoal(
|
virtual std::pair<std::shared_ptr<PathSubstitutionGoal>, kj::Promise<void>>
|
||||||
|
makePathSubstitutionGoal(
|
||||||
const StorePath & storePath,
|
const StorePath & storePath,
|
||||||
RepairFlag repair = NoRepair,
|
RepairFlag repair = NoRepair,
|
||||||
std::optional<ContentAddress> ca = std::nullopt
|
std::optional<ContentAddress> ca = std::nullopt
|
||||||
) = 0;
|
) = 0;
|
||||||
virtual std::shared_ptr<DrvOutputSubstitutionGoal> makeDrvOutputSubstitutionGoal(
|
virtual std::pair<std::shared_ptr<DrvOutputSubstitutionGoal>, kj::Promise<void>>
|
||||||
|
makeDrvOutputSubstitutionGoal(
|
||||||
const DrvOutput & id,
|
const DrvOutput & id,
|
||||||
RepairFlag repair = NoRepair,
|
RepairFlag repair = NoRepair,
|
||||||
std::optional<ContentAddress> ca = std::nullopt
|
std::optional<ContentAddress> ca = std::nullopt
|
||||||
|
@ -58,7 +60,8 @@ public:
|
||||||
* It will be a `DerivationGoal` for a `DerivedPath::Built` or
|
* It will be a `DerivationGoal` for a `DerivedPath::Built` or
|
||||||
* a `SubstitutionGoal` for a `DerivedPath::Opaque`.
|
* a `SubstitutionGoal` for a `DerivedPath::Opaque`.
|
||||||
*/
|
*/
|
||||||
virtual GoalPtr makeGoal(const DerivedPath & req, BuildMode buildMode = bmNormal) = 0;
|
virtual std::pair<GoalPtr, kj::Promise<void>>
|
||||||
|
makeGoal(const DerivedPath & req, BuildMode buildMode = bmNormal) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// elaborate hoax to let goals access factory methods while hiding them from the public
|
// elaborate hoax to let goals access factory methods while hiding them from the public
|
||||||
|
@ -94,13 +97,27 @@ private:
|
||||||
*/
|
*/
|
||||||
WeakGoals awake;
|
WeakGoals awake;
|
||||||
|
|
||||||
|
template<typename G>
|
||||||
|
struct CachedGoal
|
||||||
|
{
|
||||||
|
std::weak_ptr<G> goal;
|
||||||
|
kj::Own<kj::ForkedPromise<void>> promise;
|
||||||
|
kj::Own<kj::PromiseFulfiller<void>> fulfiller;
|
||||||
|
|
||||||
|
CachedGoal()
|
||||||
|
{
|
||||||
|
auto pf = kj::newPromiseAndFulfiller<void>();
|
||||||
|
promise = kj::heap(pf.promise.fork());
|
||||||
|
fulfiller = std::move(pf.fulfiller);
|
||||||
|
}
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Maps used to prevent multiple instantiations of a goal for the
|
* Maps used to prevent multiple instantiations of a goal for the
|
||||||
* same derivation / path.
|
* same derivation / path.
|
||||||
*/
|
*/
|
||||||
std::map<StorePath, std::weak_ptr<DerivationGoal>> derivationGoals;
|
std::map<StorePath, CachedGoal<DerivationGoal>> derivationGoals;
|
||||||
std::map<StorePath, std::weak_ptr<PathSubstitutionGoal>> substitutionGoals;
|
std::map<StorePath, CachedGoal<PathSubstitutionGoal>> substitutionGoals;
|
||||||
std::map<DrvOutput, std::weak_ptr<DrvOutputSubstitutionGoal>> drvOutputSubstitutionGoals;
|
std::map<DrvOutput, CachedGoal<DrvOutputSubstitutionGoal>> drvOutputSubstitutionGoals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache for pathContentsGood().
|
* Cache for pathContentsGood().
|
||||||
|
@ -226,21 +243,31 @@ public:
|
||||||
* @ref DerivationGoal "derivation goal"
|
* @ref DerivationGoal "derivation goal"
|
||||||
*/
|
*/
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<DerivationGoal> makeDerivationGoalCommon(
|
std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> makeDerivationGoalCommon(
|
||||||
const StorePath & drvPath, const OutputsSpec & wantedOutputs,
|
const StorePath & drvPath, const OutputsSpec & wantedOutputs,
|
||||||
std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal);
|
std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal);
|
||||||
std::shared_ptr<DerivationGoal> makeDerivationGoal(
|
std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> makeDerivationGoal(
|
||||||
const StorePath & drvPath,
|
const StorePath & drvPath,
|
||||||
const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal) override;
|
const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal) override;
|
||||||
std::shared_ptr<DerivationGoal> makeBasicDerivationGoal(
|
std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<void>> makeBasicDerivationGoal(
|
||||||
const StorePath & drvPath, const BasicDerivation & drv,
|
const StorePath & drvPath, const BasicDerivation & drv,
|
||||||
const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal) override;
|
const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ref SubstitutionGoal "substitution goal"
|
* @ref SubstitutionGoal "substitution goal"
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<PathSubstitutionGoal> makePathSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair, std::optional<ContentAddress> ca = std::nullopt) override;
|
std::pair<std::shared_ptr<PathSubstitutionGoal>, kj::Promise<void>>
|
||||||
std::shared_ptr<DrvOutputSubstitutionGoal> makeDrvOutputSubstitutionGoal(const DrvOutput & id, RepairFlag repair = NoRepair, std::optional<ContentAddress> ca = std::nullopt) override;
|
makePathSubstitutionGoal(
|
||||||
|
const StorePath & storePath,
|
||||||
|
RepairFlag repair = NoRepair,
|
||||||
|
std::optional<ContentAddress> ca = std::nullopt
|
||||||
|
) override;
|
||||||
|
std::pair<std::shared_ptr<DrvOutputSubstitutionGoal>, kj::Promise<void>>
|
||||||
|
makeDrvOutputSubstitutionGoal(
|
||||||
|
const DrvOutput & id,
|
||||||
|
RepairFlag repair = NoRepair,
|
||||||
|
std::optional<ContentAddress> ca = std::nullopt
|
||||||
|
) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a goal corresponding to the `DerivedPath`.
|
* Make a goal corresponding to the `DerivedPath`.
|
||||||
|
@ -248,13 +275,16 @@ private:
|
||||||
* It will be a `DerivationGoal` for a `DerivedPath::Built` or
|
* It will be a `DerivationGoal` for a `DerivedPath::Built` or
|
||||||
* a `SubstitutionGoal` for a `DerivedPath::Opaque`.
|
* a `SubstitutionGoal` for a `DerivedPath::Opaque`.
|
||||||
*/
|
*/
|
||||||
GoalPtr makeGoal(const DerivedPath & req, BuildMode buildMode = bmNormal) override;
|
std::pair<GoalPtr, kj::Promise<void>>
|
||||||
|
makeGoal(const DerivedPath & req, BuildMode buildMode = bmNormal) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Targets = std::map<GoalPtr, kj::Promise<void>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loop until the specified top-level goals have finished.
|
* Loop until the specified top-level goals have finished.
|
||||||
*/
|
*/
|
||||||
Goals run(std::function<Goals (GoalFactory &)> req);
|
std::vector<GoalPtr> run(std::function<Targets (GoalFactory &)> req);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* The exit status in case of failure.
|
* The exit status in case of failure.
|
||||||
|
|
Loading…
Reference in a new issue