aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/remote-store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/remote-store.cc')
-rw-r--r--src/libstore/remote-store.cc127
1 files changed, 124 insertions, 3 deletions
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index a25398ef2..347e32094 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -91,6 +91,35 @@ void write(const Store & store, Sink & out, const DrvOutput & drvOutput)
}
+BuildResult read(const Store & store, Source & from, Phantom<BuildResult> _)
+{
+ auto path = worker_proto::read(store, from, Phantom<DerivedPath> {});
+ BuildResult res { .path = path };
+ res.status = (BuildResult::Status) readInt(from);
+ from
+ >> res.errorMsg
+ >> res.timesBuilt
+ >> res.isNonDeterministic
+ >> res.startTime
+ >> res.stopTime;
+ res.builtOutputs = worker_proto::read(store, from, Phantom<DrvOutputs> {});
+ return res;
+}
+
+void write(const Store & store, Sink & to, const BuildResult & res)
+{
+ worker_proto::write(store, to, res.path);
+ to
+ << res.status
+ << res.errorMsg
+ << res.timesBuilt
+ << res.isNonDeterministic
+ << res.startTime
+ << res.stopTime;
+ worker_proto::write(store, to, res.builtOutputs);
+}
+
+
std::optional<StorePath> read(const Store & store, Source & from, Phantom<std::optional<StorePath>> _)
{
auto s = readString(from);
@@ -747,17 +776,24 @@ static void writeDerivedPaths(RemoteStore & store, ConnectionHandle & conn, cons
}
}
-void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode, std::shared_ptr<Store> evalStore)
+void RemoteStore::copyDrvsFromEvalStore(
+ const std::vector<DerivedPath> & paths,
+ std::shared_ptr<Store> evalStore)
{
if (evalStore && evalStore.get() != this) {
/* The remote doesn't have a way to access evalStore, so copy
the .drvs. */
RealisedPath::Set drvPaths2;
- for (auto & i : drvPaths)
+ for (auto & i : paths)
if (auto p = std::get_if<DerivedPath::Built>(&i))
drvPaths2.insert(p->drvPath);
copyClosure(*evalStore, *this, drvPaths2);
}
+}
+
+void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode, std::shared_ptr<Store> evalStore)
+{
+ copyDrvsFromEvalStore(drvPaths, evalStore);
auto conn(getConnection());
conn->to << wopBuildPaths;
@@ -774,6 +810,91 @@ void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMod
readInt(conn->from);
}
+std::vector<BuildResult> RemoteStore::buildPathsWithResults(
+ const std::vector<DerivedPath> & paths,
+ BuildMode buildMode,
+ std::shared_ptr<Store> evalStore)
+{
+ copyDrvsFromEvalStore(paths, evalStore);
+
+ std::optional<ConnectionHandle> conn_(getConnection());
+ auto & conn = *conn_;
+
+ if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 34) {
+ conn->to << wopBuildPathsWithResults;
+ writeDerivedPaths(*this, conn, paths);
+ conn->to << buildMode;
+ conn.processStderr();
+ return worker_proto::read(*this, conn->from, Phantom<std::vector<BuildResult>> {});
+ } else {
+ // Avoid deadlock.
+ conn_.reset();
+
+ // Note: this throws an exception if a build/substitution
+ // fails, but meh.
+ buildPaths(paths, buildMode, evalStore);
+
+ std::vector<BuildResult> results;
+
+ for (auto & path : paths) {
+ std::visit(
+ overloaded {
+ [&](const DerivedPath::Opaque & bo) {
+ results.push_back(BuildResult {
+ .status = BuildResult::Substituted,
+ .path = bo,
+ });
+ },
+ [&](const DerivedPath::Built & bfd) {
+ BuildResult res {
+ .status = BuildResult::Built,
+ .path = bfd,
+ };
+
+ OutputPathMap outputs;
+ auto drv = evalStore->readDerivation(bfd.drvPath);
+ auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
+ auto drvOutputs = drv.outputsAndOptPaths(*this);
+ for (auto & output : bfd.outputs) {
+ if (!outputHashes.count(output))
+ throw Error(
+ "the derivation '%s' doesn't have an output named '%s'",
+ printStorePath(bfd.drvPath), output);
+ auto outputId =
+ DrvOutput{outputHashes.at(output), output};
+ if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
+ auto realisation =
+ queryRealisation(outputId);
+ if (!realisation)
+ throw Error(
+ "cannot operate on an output of unbuilt "
+ "content-addressed derivation '%s'",
+ outputId.to_string());
+ res.builtOutputs.emplace(realisation->id, *realisation);
+ } else {
+ // If ca-derivations isn't enabled, assume that
+ // the output path is statically known.
+ assert(drvOutputs.count(output));
+ assert(drvOutputs.at(output).second);
+ res.builtOutputs.emplace(
+ outputId,
+ Realisation {
+ .id = outputId,
+ .outPath = *drvOutputs.at(output).second
+ });
+ }
+ }
+
+ results.push_back(res);
+ }
+ },
+ path.raw());
+ }
+
+ return results;
+ }
+}
+
BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
BuildMode buildMode)
@@ -783,7 +904,7 @@ BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicD
writeDerivation(conn->to, *this, drv);
conn->to << buildMode;
conn.processStderr();
- BuildResult res;
+ BuildResult res { .path = DerivedPath::Built { .drvPath = drvPath } };
res.status = (BuildResult::Status) readInt(conn->from);
conn->from >> res.errorMsg;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 29) {