aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build/entry-points.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/build/entry-points.cc')
-rw-r--r--src/libstore/build/entry-points.cc133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc
new file mode 100644
index 000000000..732d4785d
--- /dev/null
+++ b/src/libstore/build/entry-points.cc
@@ -0,0 +1,133 @@
+#include "machines.hh"
+#include "worker.hh"
+#include "substitution-goal.hh"
+#include "derivation-goal.hh"
+#include "local-store.hh"
+
+namespace nix {
+
+void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode)
+{
+ Worker worker(*this);
+
+ Goals goals;
+ for (auto & br : reqs) {
+ std::visit(overloaded {
+ [&](DerivedPath::Built bfd) {
+ goals.insert(worker.makeDerivationGoal(bfd.drvPath, bfd.outputs, buildMode));
+ },
+ [&](DerivedPath::Opaque bo) {
+ goals.insert(worker.makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair));
+ },
+ }, br.raw());
+ }
+
+ worker.run(goals);
+
+ StorePathSet failed;
+ std::optional<Error> ex;
+ for (auto & i : goals) {
+ if (i->ex) {
+ if (ex)
+ logError(i->ex->info());
+ else
+ ex = i->ex;
+ }
+ if (i->exitCode != Goal::ecSuccess) {
+ if (auto i2 = dynamic_cast<DerivationGoal *>(i.get())) failed.insert(i2->drvPath);
+ else if (auto i2 = dynamic_cast<PathSubstitutionGoal *>(i.get())) failed.insert(i2->storePath);
+ }
+ }
+
+ if (failed.size() == 1 && ex) {
+ ex->status = worker.exitStatus();
+ throw *ex;
+ } else if (!failed.empty()) {
+ if (ex) logError(ex->info());
+ throw Error(worker.exitStatus(), "build of %s failed", showPaths(failed));
+ }
+}
+
+BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
+ BuildMode buildMode)
+{
+ Worker worker(*this);
+ auto goal = worker.makeBasicDerivationGoal(drvPath, drv, {}, buildMode);
+
+ BuildResult result;
+
+ try {
+ worker.run(Goals{goal});
+ result = goal->getResult();
+ } catch (Error & e) {
+ result.status = BuildResult::MiscFailure;
+ result.errorMsg = e.msg();
+ }
+ // XXX: Should use `goal->queryPartialDerivationOutputMap()` once it's
+ // extended to return the full realisation for each output
+ auto staticDrvOutputs = drv.outputsAndOptPaths(*this);
+ auto outputHashes = staticOutputHashes(*this, drv);
+ for (auto & [outputName, staticOutput] : staticDrvOutputs) {
+ auto outputId = DrvOutput{outputHashes.at(outputName), outputName};
+ if (staticOutput.second)
+ result.builtOutputs.insert_or_assign(
+ outputId,
+ Realisation{ outputId, *staticOutput.second}
+ );
+ if (settings.isExperimentalFeatureEnabled("ca-derivations") && !derivationHasKnownOutputPaths(drv.type())) {
+ auto realisation = this->queryRealisation(outputId);
+ if (realisation)
+ result.builtOutputs.insert_or_assign(
+ outputId,
+ *realisation
+ );
+ }
+ }
+
+ return result;
+}
+
+
+void Store::ensurePath(const StorePath & path)
+{
+ /* If the path is already valid, we're done. */
+ if (isValidPath(path)) return;
+
+ Worker worker(*this);
+ GoalPtr goal = worker.makePathSubstitutionGoal(path);
+ Goals goals = {goal};
+
+ worker.run(goals);
+
+ if (goal->exitCode != Goal::ecSuccess) {
+ if (goal->ex) {
+ goal->ex->status = worker.exitStatus();
+ throw *goal->ex;
+ } else
+ throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path));
+ }
+}
+
+
+void LocalStore::repairPath(const StorePath & path)
+{
+ Worker worker(*this);
+ GoalPtr goal = worker.makePathSubstitutionGoal(path, Repair);
+ Goals goals = {goal};
+
+ worker.run(goals);
+
+ if (goal->exitCode != Goal::ecSuccess) {
+ /* Since substituting the path didn't work, if we have a valid
+ deriver, then rebuild the deriver. */
+ auto info = queryPathInfo(path);
+ if (info->deriver && isValidPath(*info->deriver)) {
+ goals.clear();
+ goals.insert(worker.makeDerivationGoal(*info->deriver, StringSet(), bmRepair));
+ worker.run(goals);
+ } else
+ throw Error(worker.exitStatus(), "cannot repair path '%s'", printStorePath(path));
+ }
+}
+
+}