forked from lix-project/lix
Make the build-hook work with ca derivations
- Pass it the name of the outputs rather than their output paths (as these don't exist for ca derivations) - Get the built output paths from the remote builder - Register the new received realisations
This commit is contained in:
parent
35205e2e92
commit
6fbf3fe636
|
@ -248,7 +248,7 @@ connected:
|
||||||
std::cerr << "# accept\n" << storeUri << "\n";
|
std::cerr << "# accept\n" << storeUri << "\n";
|
||||||
|
|
||||||
auto inputs = readStrings<PathSet>(source);
|
auto inputs = readStrings<PathSet>(source);
|
||||||
auto outputs = readStrings<PathSet>(source);
|
auto wantedOutputs = readStrings<StringSet>(source);
|
||||||
|
|
||||||
AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri) + ".upload-lock", true);
|
AutoCloseFD uploadLock = openLockFile(currentLoad + "/" + escapeUri(storeUri) + ".upload-lock", true);
|
||||||
|
|
||||||
|
@ -273,6 +273,7 @@ connected:
|
||||||
uploadLock = -1;
|
uploadLock = -1;
|
||||||
|
|
||||||
auto drv = store->readDerivation(*drvPath);
|
auto drv = store->readDerivation(*drvPath);
|
||||||
|
auto outputHashes = staticOutputHashes(*store, drv);
|
||||||
drv.inputSrcs = store->parseStorePathSet(inputs);
|
drv.inputSrcs = store->parseStorePathSet(inputs);
|
||||||
|
|
||||||
auto result = sshStore->buildDerivation(*drvPath, drv);
|
auto result = sshStore->buildDerivation(*drvPath, drv);
|
||||||
|
@ -280,16 +281,35 @@ connected:
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
throw Error("build of '%s' on '%s' failed: %s", store->printStorePath(*drvPath), storeUri, result.errorMsg);
|
||||||
|
|
||||||
StorePathSet missing;
|
std::set<Realisation> missingRealisations;
|
||||||
for (auto & path : outputs)
|
StorePathSet missingPaths;
|
||||||
if (!store->isValidPath(store->parseStorePath(path))) missing.insert(store->parseStorePath(path));
|
if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
|
||||||
|
for (auto & outputName : wantedOutputs) {
|
||||||
|
auto thisOutputHash = outputHashes.at(outputName);
|
||||||
|
auto thisOutputId = DrvOutput{ thisOutputHash, outputName };
|
||||||
|
if (!store->queryRealisation(thisOutputId)) {
|
||||||
|
notice("Missing output %s", outputName);
|
||||||
|
assert(result.builtOutputs.count(thisOutputId));
|
||||||
|
auto newRealisation = result.builtOutputs.at(thisOutputId);
|
||||||
|
missingRealisations.insert(newRealisation);
|
||||||
|
missingPaths.insert(newRealisation.outPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto outputPaths = drv.outputsAndOptPaths(*store);
|
||||||
|
for (auto & [outputName, hopefullyOutputPath] : outputPaths) {
|
||||||
|
assert(hopefullyOutputPath.second);
|
||||||
|
if (!store->isValidPath(*hopefullyOutputPath.second))
|
||||||
|
missingPaths.insert(*hopefullyOutputPath.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!missing.empty()) {
|
if (!missingPaths.empty()) {
|
||||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
|
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
|
||||||
if (auto localStore = store.dynamic_pointer_cast<LocalStore>())
|
if (auto localStore = store.dynamic_pointer_cast<LocalStore>())
|
||||||
for (auto & i : missing)
|
for (auto & path : missingPaths)
|
||||||
localStore->locksHeld.insert(store->printStorePath(i)); /* FIXME: ugly */
|
localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */
|
||||||
copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs, NoSubstitute);
|
copyPaths(ref<Store>(sshStore), store, missingPaths, NoRepair, NoCheckSigs, NoSubstitute);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1159,13 +1159,14 @@ HookReply DerivationGoal::tryBuildHook()
|
||||||
/* Tell the hooks the missing outputs that have to be copied back
|
/* Tell the hooks the missing outputs that have to be copied back
|
||||||
from the remote system. */
|
from the remote system. */
|
||||||
{
|
{
|
||||||
StorePathSet missingPaths;
|
StringSet missingOutputs;
|
||||||
for (auto & [_, status] : initialOutputs) {
|
for (auto & [outputName, status] : initialOutputs) {
|
||||||
if (!status.known) continue;
|
if (!status.known) continue;
|
||||||
if (buildMode != bmCheck && status.known->isValid()) continue;
|
if (buildMode != bmCheck && status.known->isValid()) continue;
|
||||||
missingPaths.insert(status.known->path);
|
missingOutputs.insert(outputName);
|
||||||
|
/* missingPaths.insert(status.known->path); */
|
||||||
}
|
}
|
||||||
worker_proto::write(worker.store, hook->sink, missingPaths);
|
worker_proto::write(worker.store, hook->sink, missingOutputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
hook->sink = FdSink();
|
hook->sink = FdSink();
|
||||||
|
|
|
@ -33,6 +33,8 @@ struct Realisation {
|
||||||
GENERATE_CMP(Realisation, me->id, me->outPath);
|
GENERATE_CMP(Realisation, me->id, me->outPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::map<DrvOutput, Realisation> DrvOutputs;
|
||||||
|
|
||||||
struct OpaquePath {
|
struct OpaquePath {
|
||||||
StorePath path;
|
StorePath path;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "callback.hh"
|
#include "callback.hh"
|
||||||
#include "filetransfer.hh"
|
#include "filetransfer.hh"
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -49,6 +50,21 @@ void write(const Store & store, Sink & out, const ContentAddress & ca)
|
||||||
out << renderContentAddress(ca);
|
out << renderContentAddress(ca);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Realisation read(const Store & store, Source & from, Phantom<Realisation> _)
|
||||||
|
{
|
||||||
|
std::string rawInput = readString(from);
|
||||||
|
return Realisation::fromJSON(
|
||||||
|
nlohmann::json::parse(rawInput),
|
||||||
|
"remote-protocol"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
void write(const Store & store, Sink & out, const Realisation & realisation)
|
||||||
|
{ out << realisation.toJSON().dump(); }
|
||||||
|
|
||||||
|
DrvOutput read(const Store & store, Source & from, Phantom<DrvOutput> _)
|
||||||
|
{ return DrvOutput::parse(readString(from)); }
|
||||||
|
void write(const Store & store, Sink & out, const DrvOutput & drvOutput)
|
||||||
|
{ out << drvOutput.to_string(); }
|
||||||
|
|
||||||
std::optional<StorePath> read(const Store & store, Source & from, Phantom<std::optional<StorePath>> _)
|
std::optional<StorePath> read(const Store & store, Source & from, Phantom<std::optional<StorePath>> _)
|
||||||
{
|
{
|
||||||
|
|
|
@ -162,6 +162,8 @@ struct BuildResult
|
||||||
non-determinism.) */
|
non-determinism.) */
|
||||||
bool isNonDeterministic = false;
|
bool isNonDeterministic = false;
|
||||||
|
|
||||||
|
DrvOutputs builtOutputs;
|
||||||
|
|
||||||
/* The start/stop times of the build (or one of the rounds, if it
|
/* The start/stop times of the build (or one of the rounds, if it
|
||||||
was repeated). */
|
was repeated). */
|
||||||
time_t startTime = 0, stopTime = 0;
|
time_t startTime = 0, stopTime = 0;
|
||||||
|
|
|
@ -86,6 +86,8 @@ namespace worker_proto {
|
||||||
MAKE_WORKER_PROTO(, std::string);
|
MAKE_WORKER_PROTO(, std::string);
|
||||||
MAKE_WORKER_PROTO(, StorePath);
|
MAKE_WORKER_PROTO(, StorePath);
|
||||||
MAKE_WORKER_PROTO(, ContentAddress);
|
MAKE_WORKER_PROTO(, ContentAddress);
|
||||||
|
MAKE_WORKER_PROTO(, Realisation);
|
||||||
|
MAKE_WORKER_PROTO(, DrvOutput);
|
||||||
|
|
||||||
MAKE_WORKER_PROTO(template<typename T>, std::set<T>);
|
MAKE_WORKER_PROTO(template<typename T>, std::set<T>);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue