aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build-result.hh16
-rw-r--r--src/libstore/build/derivation-goal.cc30
-rw-r--r--src/libstore/build/entry-points.cc29
-rw-r--r--src/libstore/build/goal.cc23
-rw-r--r--src/libstore/build/goal.hh16
-rw-r--r--src/libstore/build/local-derivation-goal.cc2
-rw-r--r--src/libstore/legacy-ssh-store.cc9
-rw-r--r--src/libstore/remote-store.cc50
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/store-api.hh3
-rw-r--r--src/libstore/worker-protocol.hh1
11 files changed, 130 insertions, 51 deletions
diff --git a/src/libstore/build-result.hh b/src/libstore/build-result.hh
index 27d1a1b6c..e07296eab 100644
--- a/src/libstore/build-result.hh
+++ b/src/libstore/build-result.hh
@@ -84,11 +84,6 @@ struct BuildResult
bool isNonDeterministic = false;
/**
- * The derivation we built or the store path we substituted.
- */
- DerivedPath path;
-
- /**
* For derivations, a mapping from the names of the wanted outputs
* to actual paths.
*/
@@ -116,4 +111,15 @@ struct BuildResult
}
};
+/**
+ * A `BuildResult` together with its "primary key".
+ */
+struct KeyedBuildResult : BuildResult
+{
+ /**
+ * The derivation we built or the store path we substituted.
+ */
+ DerivedPath path;
+};
+
}
diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc
index 26faf8c8e..606f9fd48 100644
--- a/src/libstore/build/derivation-goal.cc
+++ b/src/libstore/build/derivation-goal.cc
@@ -330,6 +330,10 @@ void DerivationGoal::outputsSubstitutionTried()
produced using a substitute. So we have to build instead. */
void DerivationGoal::gaveUpOnSubstitution()
{
+ /* Make sure checkPathValidity() from now on checks all
+ outputs. */
+ wantedOutputs = OutputsSpec::All { };
+
/* The inputs must be built before we can build this goal. */
inputDrvOutputs.clear();
if (useDerivation)
@@ -570,8 +574,6 @@ void DerivationGoal::inputsRealised()
build hook. */
state = &DerivationGoal::tryToBuild;
worker.wakeUp(shared_from_this());
-
- buildResult = BuildResult { .path = buildResult.path };
}
void DerivationGoal::started()
@@ -1452,12 +1454,28 @@ void DerivationGoal::waiteeDone(GoalPtr waitee, ExitCode result)
{
Goal::waiteeDone(waitee, result);
- if (waitee->buildResult.success())
- if (auto bfd = std::get_if<DerivedPath::Built>(&waitee->buildResult.path))
- for (auto & [output, realisation] : waitee->buildResult.builtOutputs)
+ if (!useDerivation) return;
+ auto & fullDrv = *dynamic_cast<Derivation *>(drv.get());
+
+ auto * dg = dynamic_cast<DerivationGoal *>(&*waitee);
+ if (!dg) return;
+
+ auto outputs = fullDrv.inputDrvs.find(dg->drvPath);
+ if (outputs == fullDrv.inputDrvs.end()) return;
+
+ for (auto & outputName : outputs->second) {
+ auto buildResult = dg->getBuildResult(DerivedPath::Built {
+ .drvPath = dg->drvPath,
+ .outputs = OutputsSpec::Names { outputName },
+ });
+ if (buildResult.success()) {
+ for (auto & [output, realisation] : buildResult.builtOutputs) {
inputDrvOutputs.insert_or_assign(
- { bfd->drvPath, output.outputName },
+ { dg->drvPath, output.outputName },
realisation.outPath);
+ }
+ }
+ }
}
}
diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc
index 7d725b881..74eae0692 100644
--- a/src/libstore/build/entry-points.cc
+++ b/src/libstore/build/entry-points.cc
@@ -39,7 +39,7 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
}
}
-std::vector<BuildResult> Store::buildPathsWithResults(
+std::vector<KeyedBuildResult> Store::buildPathsWithResults(
const std::vector<DerivedPath> & reqs,
BuildMode buildMode,
std::shared_ptr<Store> evalStore)
@@ -47,15 +47,23 @@ std::vector<BuildResult> Store::buildPathsWithResults(
Worker worker(*this, evalStore ? *evalStore : *this);
Goals goals;
- for (const auto & br : reqs)
- goals.insert(worker.makeGoal(br, buildMode));
+ std::vector<std::pair<const DerivedPath &, GoalPtr>> state;
+
+ for (const auto & req : reqs) {
+ auto goal = worker.makeGoal(req, buildMode);
+ goals.insert(goal);
+ state.push_back({req, goal});
+ }
worker.run(goals);
- std::vector<BuildResult> results;
+ std::vector<KeyedBuildResult> results;
- for (auto & i : goals)
- results.push_back(i->buildResult);
+ for (auto & [req, goalPtr] : state)
+ results.emplace_back(KeyedBuildResult {
+ goalPtr->getBuildResult(req),
+ /* .path = */ req,
+ });
return results;
}
@@ -68,15 +76,14 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat
try {
worker.run(Goals{goal});
- return goal->buildResult;
+ return goal->getBuildResult(DerivedPath::Built {
+ .drvPath = drvPath,
+ .outputs = OutputsSpec::All {},
+ });
} catch (Error & e) {
return BuildResult {
.status = BuildResult::MiscFailure,
.errorMsg = e.msg(),
- .path = DerivedPath::Built {
- .drvPath = drvPath,
- .outputs = OutputsSpec::All { },
- },
};
};
}
diff --git a/src/libstore/build/goal.cc b/src/libstore/build/goal.cc
index d59b94797..13b2e509a 100644
--- a/src/libstore/build/goal.cc
+++ b/src/libstore/build/goal.cc
@@ -11,6 +11,29 @@ bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) const {
}
+BuildResult Goal::getBuildResult(const DerivedPath & req) {
+ BuildResult res { buildResult };
+
+ if (auto pbp = std::get_if<DerivedPath::Built>(&req)) {
+ auto & bp = *pbp;
+
+ /* Because goals are in general shared between derived paths
+ that share the same derivation, we need to filter their
+ results to get back just the results we care about.
+ */
+
+ for (auto it = res.builtOutputs.begin(); it != res.builtOutputs.end();) {
+ if (bp.outputs.contains(it->first.outputName))
+ ++it;
+ else
+ it = res.builtOutputs.erase(it);
+ }
+ }
+
+ return res;
+}
+
+
void addToWeakGoals(WeakGoals & goals, GoalPtr p)
{
if (goals.find(p) != goals.end())
diff --git a/src/libstore/build/goal.hh b/src/libstore/build/goal.hh
index f4bf6f38b..c0e12a2ed 100644
--- a/src/libstore/build/goal.hh
+++ b/src/libstore/build/goal.hh
@@ -81,11 +81,26 @@ struct Goal : public std::enable_shared_from_this<Goal>
*/
ExitCode exitCode = ecBusy;
+protected:
/**
* Build result.
*/
BuildResult buildResult;
+public:
+
+ /**
+ * Project a `BuildResult` with just the information that pertains
+ * to the given request.
+ *
+ * In general, goals may be aliased between multiple requests, and
+ * the stored `BuildResult` has information for the union of all
+ * requests. We don't want to leak what the other request are for
+ * sake of both privacy and determinism, and this "safe accessor"
+ * ensures we don't.
+ */
+ BuildResult getBuildResult(const DerivedPath &);
+
/**
* Exception containing an error message, if any.
*/
@@ -93,7 +108,6 @@ struct Goal : public std::enable_shared_from_this<Goal>
Goal(Worker & worker, DerivedPath path)
: worker(worker)
- , buildResult { .path = std::move(path) }
{ }
virtual ~Goal()
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 58d6901d3..af937f6b1 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -1335,7 +1335,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
result.rethrow();
}
- std::vector<BuildResult> buildPathsWithResults(
+ std::vector<KeyedBuildResult> buildPathsWithResults(
const std::vector<DerivedPath> & paths,
BuildMode buildMode = bmNormal,
std::shared_ptr<Store> evalStore = nullptr) override
diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc
index d2ddbbe5f..7b40b27e0 100644
--- a/src/libstore/legacy-ssh-store.cc
+++ b/src/libstore/legacy-ssh-store.cc
@@ -287,12 +287,7 @@ public:
conn->to.flush();
- BuildResult status {
- .path = DerivedPath::Built {
- .drvPath = drvPath,
- .outputs = OutputsSpec::All { },
- },
- };
+ BuildResult status;
status.status = (BuildResult::Status) readInt(conn->from);
conn->from >> status.errorMsg;
@@ -330,7 +325,7 @@ public:
conn->to.flush();
- BuildResult result { .path = DerivedPath::Opaque { StorePath::dummy } };
+ BuildResult result;
result.status = (BuildResult::Status) readInt(conn->from);
if (!result.success()) {
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index b862902d1..734e6f27f 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -125,10 +125,26 @@ void write(const Store & store, Sink & out, const DrvOutput & drvOutput)
}
-BuildResult read(const Store & store, Source & from, Phantom<BuildResult> _)
+KeyedBuildResult read(const Store & store, Source & from, Phantom<KeyedBuildResult> _)
{
auto path = worker_proto::read(store, from, Phantom<DerivedPath> {});
- BuildResult res { .path = path };
+ auto br = worker_proto::read(store, from, Phantom<BuildResult> {});
+ return KeyedBuildResult {
+ std::move(br),
+ /* .path = */ std::move(path),
+ };
+}
+
+void write(const Store & store, Sink & to, const KeyedBuildResult & res)
+{
+ worker_proto::write(store, to, res.path);
+ worker_proto::write(store, to, static_cast<const BuildResult &>(res));
+}
+
+
+BuildResult read(const Store & store, Source & from, Phantom<BuildResult> _)
+{
+ BuildResult res;
res.status = (BuildResult::Status) readInt(from);
from
>> res.errorMsg
@@ -142,7 +158,6 @@ BuildResult read(const Store & store, Source & from, Phantom<BuildResult> _)
void write(const Store & store, Sink & to, const BuildResult & res)
{
- worker_proto::write(store, to, res.path);
to
<< res.status
<< res.errorMsg
@@ -865,7 +880,7 @@ void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMod
readInt(conn->from);
}
-std::vector<BuildResult> RemoteStore::buildPathsWithResults(
+std::vector<KeyedBuildResult> RemoteStore::buildPathsWithResults(
const std::vector<DerivedPath> & paths,
BuildMode buildMode,
std::shared_ptr<Store> evalStore)
@@ -880,7 +895,7 @@ std::vector<BuildResult> RemoteStore::buildPathsWithResults(
writeDerivedPaths(*this, conn, paths);
conn->to << buildMode;
conn.processStderr();
- return worker_proto::read(*this, conn->from, Phantom<std::vector<BuildResult>> {});
+ return worker_proto::read(*this, conn->from, Phantom<std::vector<KeyedBuildResult>> {});
} else {
// Avoid deadlock.
conn_.reset();
@@ -889,21 +904,25 @@ std::vector<BuildResult> RemoteStore::buildPathsWithResults(
// fails, but meh.
buildPaths(paths, buildMode, evalStore);
- std::vector<BuildResult> results;
+ std::vector<KeyedBuildResult> results;
for (auto & path : paths) {
std::visit(
overloaded {
[&](const DerivedPath::Opaque & bo) {
- results.push_back(BuildResult {
- .status = BuildResult::Substituted,
- .path = bo,
+ results.push_back(KeyedBuildResult {
+ {
+ .status = BuildResult::Substituted,
+ },
+ /* .path = */ bo,
});
},
[&](const DerivedPath::Built & bfd) {
- BuildResult res {
- .status = BuildResult::Built,
- .path = bfd,
+ KeyedBuildResult res {
+ {
+ .status = BuildResult::Built
+ },
+ /* .path = */ bfd,
};
OutputPathMap outputs;
@@ -952,12 +971,7 @@ BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicD
writeDerivation(conn->to, *this, drv);
conn->to << buildMode;
conn.processStderr();
- BuildResult res {
- .path = DerivedPath::Built {
- .drvPath = drvPath,
- .outputs = OutputsSpec::All { },
- },
- };
+ BuildResult res;
res.status = (BuildResult::Status) readInt(conn->from);
conn->from >> res.errorMsg;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 29) {
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 1c45f543e..a30466647 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -114,7 +114,7 @@ public:
void buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override;
- std::vector<BuildResult> buildPathsWithResults(
+ std::vector<KeyedBuildResult> buildPathsWithResults(
const std::vector<DerivedPath> & paths,
BuildMode buildMode,
std::shared_ptr<Store> evalStore) override;
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 5bee272bf..9d6880de9 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -92,6 +92,7 @@ enum BuildMode { bmNormal, bmRepair, bmCheck };
enum TrustedFlag : bool { NotTrusted = false, Trusted = true };
struct BuildResult;
+struct KeyedBuildResult;
typedef std::map<StorePath, std::optional<ContentAddress>> StorePathCAMap;
@@ -575,7 +576,7 @@ public:
* case of a build/substitution error, this function won't throw an
* exception, but return a BuildResult containing an error message.
*/
- virtual std::vector<BuildResult> buildPathsWithResults(
+ virtual std::vector<KeyedBuildResult> buildPathsWithResults(
const std::vector<DerivedPath> & paths,
BuildMode buildMode = bmNormal,
std::shared_ptr<Store> evalStore = nullptr);
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index c7a6f8688..34b2fc17b 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -103,6 +103,7 @@ MAKE_WORKER_PROTO(, DerivedPath);
MAKE_WORKER_PROTO(, Realisation);
MAKE_WORKER_PROTO(, DrvOutput);
MAKE_WORKER_PROTO(, BuildResult);
+MAKE_WORKER_PROTO(, KeyedBuildResult);
MAKE_WORKER_PROTO(, std::optional<TrustedFlag>);
MAKE_WORKER_PROTO(template<typename T>, std::vector<T>);