aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-01-11 18:57:18 -0500
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-01-11 18:57:18 -0500
commitce2f91d356438297fd795bd3edb8f9f4536db7da (patch)
treef5bfc224151eb15fdd25f1e93b367756ff237cab /src/libstore/build
parenta7c0cff07f3e1af60bdbcd5bf7e13f8ae768da90 (diff)
Split `OutputsSpec` and `ExtendedOutputsSpec`, use the former more
`DerivedPath::Built` and `DerivationGoal` were previously using a regular set with the convention that the empty set means all outputs. But it is easy to forget about this rule when processing those sets. Using `OutputSpec` forces us to get it right.
Diffstat (limited to 'src/libstore/build')
-rw-r--r--src/libstore/build/derivation-goal.cc47
-rw-r--r--src/libstore/build/derivation-goal.hh9
-rw-r--r--src/libstore/build/entry-points.cc3
-rw-r--r--src/libstore/build/local-derivation-goal.cc2
-rw-r--r--src/libstore/build/worker.cc6
-rw-r--r--src/libstore/build/worker.hh6
6 files changed, 40 insertions, 33 deletions
diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc
index 5e86b5269..98c1ddaae 100644
--- a/src/libstore/build/derivation-goal.cc
+++ b/src/libstore/build/derivation-goal.cc
@@ -63,7 +63,7 @@
namespace nix {
DerivationGoal::DerivationGoal(const StorePath & drvPath,
- const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode)
+ const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode)
: Goal(worker, DerivedPath::Built { .drvPath = drvPath, .outputs = wantedOutputs })
, useDerivation(true)
, drvPath(drvPath)
@@ -82,7 +82,7 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath,
DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv,
- const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode)
+ const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode)
: Goal(worker, DerivedPath::Built { .drvPath = drvPath, .outputs = wantedOutputs })
, useDerivation(false)
, drvPath(drvPath)
@@ -142,18 +142,11 @@ void DerivationGoal::work()
(this->*state)();
}
-void DerivationGoal::addWantedOutputs(const StringSet & outputs)
+void DerivationGoal::addWantedOutputs(const OutputsSpec & outputs)
{
- /* If we already want all outputs, there is nothing to do. */
- if (wantedOutputs.empty()) return;
-
- if (outputs.empty()) {
- wantedOutputs.clear();
+ bool newOutputs = wantedOutputs.merge(outputs);
+ if (newOutputs)
needRestart = true;
- } else
- for (auto & i : outputs)
- if (wantedOutputs.insert(i).second)
- needRestart = true;
}
@@ -390,7 +383,7 @@ void DerivationGoal::repairClosure()
auto outputs = queryDerivationOutputMap();
StorePathSet outputClosure;
for (auto & i : outputs) {
- if (!wantOutput(i.first, wantedOutputs)) continue;
+ if (!wantedOutputs.contains(i.first)) continue;
worker.store.computeFSClosure(i.second, outputClosure);
}
@@ -422,7 +415,7 @@ void DerivationGoal::repairClosure()
if (drvPath2 == outputsToDrv.end())
addWaitee(upcast_goal(worker.makePathSubstitutionGoal(i, Repair)));
else
- addWaitee(worker.makeDerivationGoal(drvPath2->second, StringSet(), bmRepair));
+ addWaitee(worker.makeDerivationGoal(drvPath2->second, OutputsSpec::All(), bmRepair));
}
if (waitees.empty()) {
@@ -991,10 +984,15 @@ void DerivationGoal::resolvedFinished()
StorePathSet outputPaths;
- // `wantedOutputs` might be empty, which means “all the outputs”
- auto realWantedOutputs = wantedOutputs;
- if (realWantedOutputs.empty())
- realWantedOutputs = resolvedDrv.outputNames();
+ // `wantedOutputs` might merely indicate “all the outputs”
+ auto realWantedOutputs = std::visit(overloaded {
+ [&](const OutputsSpec::All &) {
+ return resolvedDrv.outputNames();
+ },
+ [&](const OutputsSpec::Names & names) {
+ return names;
+ },
+ }, wantedOutputs.raw());
for (auto & wantedOutput : realWantedOutputs) {
auto initialOutput = get(initialOutputs, wantedOutput);
@@ -1322,7 +1320,14 @@ std::pair<bool, DrvOutputs> DerivationGoal::checkPathValidity()
if (!drv->type().isPure()) return { false, {} };
bool checkHash = buildMode == bmRepair;
- auto wantedOutputsLeft = wantedOutputs;
+ auto wantedOutputsLeft = std::visit(overloaded {
+ [&](const OutputsSpec::All &) {
+ return StringSet {};
+ },
+ [&](const OutputsSpec::Names & names) {
+ return names;
+ },
+ }, wantedOutputs.raw());
DrvOutputs validOutputs;
for (auto & i : queryPartialDerivationOutputMap()) {
@@ -1331,7 +1336,7 @@ std::pair<bool, DrvOutputs> DerivationGoal::checkPathValidity()
// this is an invalid output, gets catched with (!wantedOutputsLeft.empty())
continue;
auto & info = *initialOutput;
- info.wanted = wantOutput(i.first, wantedOutputs);
+ info.wanted = wantedOutputs.contains(i.first);
if (info.wanted)
wantedOutputsLeft.erase(i.first);
if (i.second) {
@@ -1369,7 +1374,7 @@ std::pair<bool, DrvOutputs> DerivationGoal::checkPathValidity()
validOutputs.emplace(drvOutput, Realisation { drvOutput, info.known->path });
}
- // If we requested all the outputs via the empty set, we are always fine.
+ // 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())
diff --git a/src/libstore/build/derivation-goal.hh b/src/libstore/build/derivation-goal.hh
index d33e04cbc..707e38b4b 100644
--- a/src/libstore/build/derivation-goal.hh
+++ b/src/libstore/build/derivation-goal.hh
@@ -2,6 +2,7 @@
#include "parsed-derivations.hh"
#include "lock.hh"
+#include "outputs-spec.hh"
#include "store-api.hh"
#include "pathlocks.hh"
#include "goal.hh"
@@ -55,7 +56,7 @@ struct DerivationGoal : public Goal
/* The specific outputs that we need to build. Empty means all of
them. */
- StringSet wantedOutputs;
+ OutputsSpec wantedOutputs;
/* Mapping from input derivations + output names to actual store
paths. This is filled in by waiteeDone() as each dependency
@@ -128,10 +129,10 @@ struct DerivationGoal : public Goal
std::string machineName;
DerivationGoal(const StorePath & drvPath,
- const StringSet & wantedOutputs, Worker & worker,
+ const OutputsSpec & wantedOutputs, Worker & worker,
BuildMode buildMode = bmNormal);
DerivationGoal(const StorePath & drvPath, const BasicDerivation & drv,
- const StringSet & wantedOutputs, Worker & worker,
+ const OutputsSpec & wantedOutputs, Worker & worker,
BuildMode buildMode = bmNormal);
virtual ~DerivationGoal();
@@ -142,7 +143,7 @@ struct DerivationGoal : public Goal
void work() override;
/* Add wanted outputs to an already existing derivation goal. */
- void addWantedOutputs(const StringSet & outputs);
+ void addWantedOutputs(const OutputsSpec & outputs);
/* The states. */
void getDerivation();
diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc
index e1b80165e..df7722733 100644
--- a/src/libstore/build/entry-points.cc
+++ b/src/libstore/build/entry-points.cc
@@ -130,7 +130,8 @@ void LocalStore::repairPath(const StorePath & path)
auto info = queryPathInfo(path);
if (info->deriver && isValidPath(*info->deriver)) {
goals.clear();
- goals.insert(worker.makeDerivationGoal(*info->deriver, StringSet(), bmRepair));
+ // FIXME: Should just build the specific output we need.
+ goals.insert(worker.makeDerivationGoal(*info->deriver, OutputsSpec::All { }, bmRepair));
worker.run(goals);
} else
throw Error(worker.exitStatus(), "cannot repair path '%s'", printStorePath(path));
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 488e06d8c..09cb6b233 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2735,7 +2735,7 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
signRealisation(thisRealisation);
worker.store.registerDrvOutput(thisRealisation);
}
- if (wantOutput(outputName, wantedOutputs))
+ if (wantedOutputs.contains(outputName))
builtOutputs.emplace(thisRealisation.id, thisRealisation);
}
diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc
index b192fbc77..b94fb8416 100644
--- a/src/libstore/build/worker.cc
+++ b/src/libstore/build/worker.cc
@@ -42,7 +42,7 @@ Worker::~Worker()
std::shared_ptr<DerivationGoal> Worker::makeDerivationGoalCommon(
const StorePath & drvPath,
- const StringSet & wantedOutputs,
+ const OutputsSpec & wantedOutputs,
std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal)
{
std::weak_ptr<DerivationGoal> & goal_weak = derivationGoals[drvPath];
@@ -59,7 +59,7 @@ std::shared_ptr<DerivationGoal> Worker::makeDerivationGoalCommon(
std::shared_ptr<DerivationGoal> Worker::makeDerivationGoal(const StorePath & drvPath,
- const StringSet & wantedOutputs, BuildMode buildMode)
+ const OutputsSpec & wantedOutputs, BuildMode buildMode)
{
return makeDerivationGoalCommon(drvPath, wantedOutputs, [&]() -> std::shared_ptr<DerivationGoal> {
return !dynamic_cast<LocalStore *>(&store)
@@ -70,7 +70,7 @@ std::shared_ptr<DerivationGoal> Worker::makeDerivationGoal(const StorePath & drv
std::shared_ptr<DerivationGoal> Worker::makeBasicDerivationGoal(const StorePath & drvPath,
- const BasicDerivation & drv, const StringSet & wantedOutputs, BuildMode buildMode)
+ const BasicDerivation & drv, const OutputsSpec & wantedOutputs, BuildMode buildMode)
{
return makeDerivationGoalCommon(drvPath, wantedOutputs, [&]() -> std::shared_ptr<DerivationGoal> {
return !dynamic_cast<LocalStore *>(&store)
diff --git a/src/libstore/build/worker.hh b/src/libstore/build/worker.hh
index a1e036a96..6d68d3cf1 100644
--- a/src/libstore/build/worker.hh
+++ b/src/libstore/build/worker.hh
@@ -140,15 +140,15 @@ public:
/* derivation goal */
private:
std::shared_ptr<DerivationGoal> makeDerivationGoalCommon(
- const StorePath & drvPath, const StringSet & wantedOutputs,
+ const StorePath & drvPath, const OutputsSpec & wantedOutputs,
std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal);
public:
std::shared_ptr<DerivationGoal> makeDerivationGoal(
const StorePath & drvPath,
- const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);
+ const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal);
std::shared_ptr<DerivationGoal> makeBasicDerivationGoal(
const StorePath & drvPath, const BasicDerivation & drv,
- const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);
+ const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal);
/* substitution goal */
std::shared_ptr<PathSubstitutionGoal> makePathSubstitutionGoal(const StorePath & storePath, RepairFlag repair = NoRepair, std::optional<ContentAddress> ca = std::nullopt);