forked from lix-project/hydra
Fix build
This commit is contained in:
parent
7b8a3acbf0
commit
7d3ba616a9
|
@ -453,29 +453,29 @@ int main(int argc, char * * argv)
|
||||||
job["constituents"].push_back(drvPath2);
|
job["constituents"].push_back(drvPath2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::string drvPath = job["drvPath"];
|
auto drvPath = store->parseStorePath((std::string) job["drvPath"]);
|
||||||
auto drv = readDerivation(*store, drvPath);
|
auto drv = store->readDerivation(drvPath);
|
||||||
|
|
||||||
for (std::string jobName2 : *named) {
|
for (std::string jobName2 : *named) {
|
||||||
auto job2 = state->jobs.find(jobName2);
|
auto job2 = state->jobs.find(jobName2);
|
||||||
if (job2 == state->jobs.end())
|
if (job2 == state->jobs.end())
|
||||||
throw Error("aggregate job '%s' references non-existent job '%s'", jobName, jobName2);
|
throw Error("aggregate job '%s' references non-existent job '%s'", jobName, jobName2);
|
||||||
std::string drvPath2 = (*job2)["drvPath"];
|
auto drvPath2 = store->parseStorePath((std::string) (*job2)["drvPath"]);
|
||||||
auto drv2 = readDerivation(*store, drvPath2);
|
auto drv2 = store->readDerivation(drvPath2);
|
||||||
job["constituents"].push_back(drvPath2);
|
job["constituents"].push_back(store->printStorePath(drvPath2));
|
||||||
drv.inputDrvs[store->parseStorePath(drvPath2)] = {drv2.outputs.begin()->first};
|
drv.inputDrvs[drvPath2] = {drv2.outputs.begin()->first};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string drvName(store->parseStorePath(drvPath).name());
|
std::string drvName(drvPath.name());
|
||||||
assert(hasSuffix(drvName, drvExtension));
|
assert(hasSuffix(drvName, drvExtension));
|
||||||
drvName.resize(drvName.size() - drvExtension.size());
|
drvName.resize(drvName.size() - drvExtension.size());
|
||||||
auto h = hashDerivationModulo(*store, drv, true);
|
auto h = hashDerivationModulo(*store, drv, true);
|
||||||
auto outPath = store->makeOutputPath("out", h, drvName);
|
auto outPath = store->makeOutputPath("out", h, drvName);
|
||||||
drv.env["out"] = store->printStorePath(outPath);
|
drv.env["out"] = store->printStorePath(outPath);
|
||||||
drv.outputs.insert_or_assign("out", DerivationOutput { .path = outPath });
|
drv.outputs.insert_or_assign("out", DerivationOutput { .output = DerivationOutputInputAddressed { .path = outPath } });
|
||||||
auto newDrvPath = store->printStorePath(writeDerivation(store, drv, drvName));
|
auto newDrvPath = store->printStorePath(writeDerivation(store, drv, drvName));
|
||||||
|
|
||||||
debug("rewrote aggregate derivation %s -> %s", drvPath, newDrvPath);
|
debug("rewrote aggregate derivation %s -> %s", store->printStorePath(drvPath), newDrvPath);
|
||||||
|
|
||||||
job["drvPath"] = newDrvPath;
|
job["drvPath"] = newDrvPath;
|
||||||
job["outputs"]["out"] = store->printStorePath(outPath);
|
job["outputs"]["out"] = store->printStorePath(outPath);
|
||||||
|
|
|
@ -260,12 +260,13 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
inputs.insert(p);
|
inputs.insert(p);
|
||||||
|
|
||||||
for (auto & input : step->drv->inputDrvs) {
|
for (auto & input : step->drv->inputDrvs) {
|
||||||
Derivation drv2 = readDerivation(*localStore, localStore->printStorePath(input.first));
|
auto drv2 = localStore->readDerivation(input.first);
|
||||||
for (auto & name : input.second) {
|
for (auto & name : input.second) {
|
||||||
auto i = drv2.outputs.find(name);
|
if (auto i = get(drv2.outputs, name)) {
|
||||||
if (i == drv2.outputs.end()) continue;
|
auto outPath = i->path(*localStore, drv2.name);
|
||||||
inputs.insert(i->second.path);
|
inputs.insert(outPath);
|
||||||
basicDrv.inputSrcs.insert(i->second.path);
|
basicDrv.inputSrcs.insert(outPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +434,7 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
|
|
||||||
auto now1 = std::chrono::steady_clock::now();
|
auto now1 = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
auto outputs = step->drv->outputPaths();
|
auto outputs = step->drv->outputPaths(*localStore);
|
||||||
|
|
||||||
/* Get info about each output path. */
|
/* Get info about each output path. */
|
||||||
std::map<StorePath, ValidPathInfo> infos;
|
std::map<StorePath, ValidPathInfo> infos;
|
||||||
|
|
|
@ -16,7 +16,7 @@ BuildOutput getBuildOutput(
|
||||||
BuildOutput res;
|
BuildOutput res;
|
||||||
|
|
||||||
/* Compute the closure size. */
|
/* Compute the closure size. */
|
||||||
auto outputs = drv.outputPaths();
|
auto outputs = drv.outputPaths(*store);
|
||||||
StorePathSet closure;
|
StorePathSet closure;
|
||||||
for (auto & output : outputs)
|
for (auto & output : outputs)
|
||||||
store->computeFSClosure(output, closure);
|
store->computeFSClosure(output, closure);
|
||||||
|
@ -106,10 +106,11 @@ BuildOutput getBuildOutput(
|
||||||
if (!explicitProducts) {
|
if (!explicitProducts) {
|
||||||
for (auto & output : drv.outputs) {
|
for (auto & output : drv.outputs) {
|
||||||
BuildProduct product;
|
BuildProduct product;
|
||||||
product.path = store->printStorePath(output.second.path);
|
auto outPath = output.second.path(*store, drv.name);
|
||||||
|
product.path = store->printStorePath(outPath);
|
||||||
product.type = "nix-build";
|
product.type = "nix-build";
|
||||||
product.subtype = output.first == "out" ? "" : output.first;
|
product.subtype = output.first == "out" ? "" : output.first;
|
||||||
product.name = output.second.path.name();
|
product.name = outPath.name();
|
||||||
|
|
||||||
auto file = narMembers.find(product.path);
|
auto file = narMembers.find(product.path);
|
||||||
assert(file != narMembers.end());
|
assert(file != narMembers.end());
|
||||||
|
|
|
@ -12,8 +12,8 @@ struct BuildProduct
|
||||||
nix::Path path, defaultPath;
|
nix::Path path, defaultPath;
|
||||||
std::string type, subtype, name;
|
std::string type, subtype, name;
|
||||||
bool isRegular = false;
|
bool isRegular = false;
|
||||||
nix::Hash sha256hash;
|
std::optional<nix::Hash> sha256hash;
|
||||||
off_t fileSize = 0;
|
std::optional<off_t> fileSize;
|
||||||
BuildProduct() { }
|
BuildProduct() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -274,7 +274,7 @@ State::StepResult State::doBuildStep(nix::ref<Store> destStore,
|
||||||
|
|
||||||
assert(stepNr);
|
assert(stepNr);
|
||||||
|
|
||||||
for (auto & path : step->drv->outputPaths())
|
for (auto & path : step->drv->outputPaths(*localStore))
|
||||||
addRoot(path);
|
addRoot(path);
|
||||||
|
|
||||||
/* Register success in the database for all Build objects that
|
/* Register success in the database for all Build objects that
|
||||||
|
@ -463,7 +463,7 @@ void State::failStep(
|
||||||
/* Remember failed paths in the database so that they
|
/* Remember failed paths in the database so that they
|
||||||
won't be built again. */
|
won't be built again. */
|
||||||
if (result.stepStatus != bsCachedFailure && result.canCache)
|
if (result.stepStatus != bsCachedFailure && result.canCache)
|
||||||
for (auto & path : step->drv->outputPaths())
|
for (auto & path : step->drv->outputPaths(*localStore))
|
||||||
txn.exec_params0("insert into FailedPaths values ($1)", localStore->printStorePath(path));
|
txn.exec_params0("insert into FailedPaths values ($1)", localStore->printStorePath(path));
|
||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
|
@ -260,7 +260,7 @@ unsigned int State::createBuildStep(pqxx::work & txn, time_t startTime, BuildID
|
||||||
for (auto & output : step->drv->outputs)
|
for (auto & output : step->drv->outputs)
|
||||||
txn.exec_params0
|
txn.exec_params0
|
||||||
("insert into BuildStepOutputs (build, stepnr, name, path) values ($1, $2, $3, $4)",
|
("insert into BuildStepOutputs (build, stepnr, name, path) values ($1, $2, $3, $4)",
|
||||||
buildId, stepNr, output.first, localStore->printStorePath(output.second.path));
|
buildId, stepNr, output.first, localStore->printStorePath(output.second.path(*localStore, step->drv->name)));
|
||||||
|
|
||||||
if (status == bsBusy)
|
if (status == bsBusy)
|
||||||
txn.exec(fmt("notify step_started, '%d\t%d'", buildId, stepNr));
|
txn.exec(fmt("notify step_started, '%d\t%d'", buildId, stepNr));
|
||||||
|
@ -412,8 +412,8 @@ void State::markSucceededBuild(pqxx::work & txn, Build::ptr build,
|
||||||
productNr++,
|
productNr++,
|
||||||
product.type,
|
product.type,
|
||||||
product.subtype,
|
product.subtype,
|
||||||
product.isRegular ? std::make_optional(product.fileSize) : std::nullopt,
|
product.fileSize ? std::make_optional(*product.fileSize) : std::nullopt,
|
||||||
product.isRegular ? std::make_optional(product.sha256hash.to_string(Base16, false)) : std::nullopt,
|
product.sha256hash ? std::make_optional(product.sha256hash->to_string(Base16, false)) : std::nullopt,
|
||||||
product.path,
|
product.path,
|
||||||
product.name,
|
product.name,
|
||||||
product.defaultPath);
|
product.defaultPath);
|
||||||
|
@ -441,7 +441,7 @@ void State::markSucceededBuild(pqxx::work & txn, Build::ptr build,
|
||||||
bool State::checkCachedFailure(Step::ptr step, Connection & conn)
|
bool State::checkCachedFailure(Step::ptr step, Connection & conn)
|
||||||
{
|
{
|
||||||
pqxx::work txn(conn);
|
pqxx::work txn(conn);
|
||||||
for (auto & path : step->drv->outputPaths())
|
for (auto & path : step->drv->outputPaths(*localStore))
|
||||||
if (!txn.exec_params("select 1 from FailedPaths where path = $1", localStore->printStorePath(path)).empty())
|
if (!txn.exec_params("select 1 from FailedPaths where path = $1", localStore->printStorePath(path)).empty())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -637,12 +637,7 @@ void State::dumpStatus(Connection & conn)
|
||||||
auto nested2 = nested.object("s3");
|
auto nested2 = nested.object("s3");
|
||||||
auto & s3Stats = s3Store->getS3Stats();
|
auto & s3Stats = s3Store->getS3Stats();
|
||||||
nested2.attr("put", s3Stats.put);
|
nested2.attr("put", s3Stats.put);
|
||||||
nested2.attr("putBytes", s3Stats.putBytes);
|
|
||||||
nested2.attr("putTimeMs", s3Stats.putTimeMs);
|
nested2.attr("putTimeMs", s3Stats.putTimeMs);
|
||||||
nested2.attr("putSpeed",
|
|
||||||
s3Stats.putTimeMs
|
|
||||||
? (double) s3Stats.putBytes / s3Stats.putTimeMs * 1000.0 / (1024.0 * 1024.0)
|
|
||||||
: 0.0);
|
|
||||||
nested2.attr("get", s3Stats.get);
|
nested2.attr("get", s3Stats.get);
|
||||||
nested2.attr("getBytes", s3Stats.getBytes);
|
nested2.attr("getBytes", s3Stats.getBytes);
|
||||||
nested2.attr("getTimeMs", s3Stats.getTimeMs);
|
nested2.attr("getTimeMs", s3Stats.getTimeMs);
|
||||||
|
|
|
@ -39,13 +39,13 @@ struct Extractor : ParseSink
|
||||||
std::optional<unsigned long long> expectedSize;
|
std::optional<unsigned long long> expectedSize;
|
||||||
std::unique_ptr<HashSink> hashSink;
|
std::unique_ptr<HashSink> hashSink;
|
||||||
|
|
||||||
void preallocateContents(unsigned long long size) override
|
void preallocateContents(uint64_t size) override
|
||||||
{
|
{
|
||||||
expectedSize = size;
|
expectedSize = size;
|
||||||
hashSink = std::make_unique<HashSink>(htSHA256);
|
hashSink = std::make_unique<HashSink>(htSHA256);
|
||||||
}
|
}
|
||||||
|
|
||||||
void receiveContents(unsigned char * data, unsigned int len) override
|
void receiveContents(unsigned char * data, size_t len) override
|
||||||
{
|
{
|
||||||
assert(expectedSize);
|
assert(expectedSize);
|
||||||
assert(curMember);
|
assert(curMember);
|
||||||
|
|
|
@ -176,10 +176,10 @@ bool State::getQueuedBuilds(Connection & conn,
|
||||||
if (!res[0].is_null()) propagatedFrom = res[0].as<BuildID>();
|
if (!res[0].is_null()) propagatedFrom = res[0].as<BuildID>();
|
||||||
|
|
||||||
if (!propagatedFrom) {
|
if (!propagatedFrom) {
|
||||||
for (auto & output : ex.step->drv->outputs) {
|
for (auto & output : ex.step->drv->outputPaths(*localStore)) {
|
||||||
auto res = txn.exec_params
|
auto res = txn.exec_params
|
||||||
("select max(s.build) from BuildSteps s join BuildStepOutputs o on s.build = o.build where path = $1 and startTime != 0 and stopTime != 0 and status = 1",
|
("select max(s.build) from BuildSteps s join BuildStepOutputs o on s.build = o.build where path = $1 and startTime != 0 and stopTime != 0 and status = 1",
|
||||||
localStore->printStorePath(output.second.path));
|
localStore->printStorePath(output));
|
||||||
if (!res[0][0].is_null()) {
|
if (!res[0][0].is_null()) {
|
||||||
propagatedFrom = res[0][0].as<BuildID>();
|
propagatedFrom = res[0][0].as<BuildID>();
|
||||||
break;
|
break;
|
||||||
|
@ -218,10 +218,10 @@ bool State::getQueuedBuilds(Connection & conn,
|
||||||
/* If we didn't get a step, it means the step's outputs are
|
/* If we didn't get a step, it means the step's outputs are
|
||||||
all valid. So we mark this as a finished, cached build. */
|
all valid. So we mark this as a finished, cached build. */
|
||||||
if (!step) {
|
if (!step) {
|
||||||
Derivation drv = readDerivation(*localStore, localStore->printStorePath(build->drvPath));
|
auto drv = localStore->readDerivation(build->drvPath);
|
||||||
BuildOutput res = getBuildOutputCached(conn, destStore, drv);
|
BuildOutput res = getBuildOutputCached(conn, destStore, drv);
|
||||||
|
|
||||||
for (auto & path : drv.outputPaths())
|
for (auto & path : drv.outputPaths(*localStore))
|
||||||
addRoot(path);
|
addRoot(path);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -427,7 +427,7 @@ Step::ptr State::createStep(ref<Store> destStore,
|
||||||
‘steps’ before this point, but that doesn't matter because
|
‘steps’ before this point, but that doesn't matter because
|
||||||
it's not runnable yet, and other threads won't make it
|
it's not runnable yet, and other threads won't make it
|
||||||
runnable while step->created == false. */
|
runnable while step->created == false. */
|
||||||
step->drv = std::make_unique<Derivation>(readDerivation(*localStore, localStore->printStorePath(drvPath)));
|
step->drv = std::make_unique<Derivation>(localStore->readDerivation(drvPath));
|
||||||
step->parsedDrv = std::make_unique<ParsedDerivation>(drvPath, *step->drv);
|
step->parsedDrv = std::make_unique<ParsedDerivation>(drvPath, *step->drv);
|
||||||
|
|
||||||
step->preferLocalBuild = step->parsedDrv->willBuildLocally();
|
step->preferLocalBuild = step->parsedDrv->willBuildLocally();
|
||||||
|
@ -453,10 +453,10 @@ Step::ptr State::createStep(ref<Store> destStore,
|
||||||
|
|
||||||
/* Are all outputs valid? */
|
/* Are all outputs valid? */
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
auto outputs = step->drv->outputPaths();
|
auto outputs = step->drv->outputPaths(*localStore);
|
||||||
DerivationOutputs missing;
|
DerivationOutputs missing;
|
||||||
for (auto & i : step->drv->outputs)
|
for (auto & i : step->drv->outputs)
|
||||||
if (!destStore->isValidPath(i.second.path)) {
|
if (!destStore->isValidPath(i.second.path(*localStore, step->drv->name))) {
|
||||||
valid = false;
|
valid = false;
|
||||||
missing.insert_or_assign(i.first, i.second);
|
missing.insert_or_assign(i.first, i.second);
|
||||||
}
|
}
|
||||||
|
@ -467,11 +467,12 @@ Step::ptr State::createStep(ref<Store> destStore,
|
||||||
|
|
||||||
size_t avail = 0;
|
size_t avail = 0;
|
||||||
for (auto & i : missing) {
|
for (auto & i : missing) {
|
||||||
if (/* localStore != destStore && */ localStore->isValidPath(i.second.path))
|
auto path = i.second.path(*localStore, step->drv->name);
|
||||||
|
if (/* localStore != destStore && */ localStore->isValidPath(path))
|
||||||
avail++;
|
avail++;
|
||||||
else if (useSubstitutes) {
|
else if (useSubstitutes) {
|
||||||
SubstitutablePathInfos infos;
|
SubstitutablePathInfos infos;
|
||||||
localStore->querySubstitutablePathInfos({i.second.path}, infos);
|
localStore->querySubstitutablePathInfos({{path, {}}}, infos);
|
||||||
if (infos.size() == 1)
|
if (infos.size() == 1)
|
||||||
avail++;
|
avail++;
|
||||||
}
|
}
|
||||||
|
@ -480,35 +481,37 @@ Step::ptr State::createStep(ref<Store> destStore,
|
||||||
if (missing.size() == avail) {
|
if (missing.size() == avail) {
|
||||||
valid = true;
|
valid = true;
|
||||||
for (auto & i : missing) {
|
for (auto & i : missing) {
|
||||||
|
auto path = i.second.path(*localStore, step->drv->name);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
time_t startTime = time(0);
|
time_t startTime = time(0);
|
||||||
|
|
||||||
if (localStore->isValidPath(i.second.path))
|
if (localStore->isValidPath(path))
|
||||||
printInfo("copying output ‘%1%’ of ‘%2%’ from local store",
|
printInfo("copying output ‘%1%’ of ‘%2%’ from local store",
|
||||||
localStore->printStorePath(i.second.path),
|
localStore->printStorePath(path),
|
||||||
localStore->printStorePath(drvPath));
|
localStore->printStorePath(drvPath));
|
||||||
else {
|
else {
|
||||||
printInfo("substituting output ‘%1%’ of ‘%2%’",
|
printInfo("substituting output ‘%1%’ of ‘%2%’",
|
||||||
localStore->printStorePath(i.second.path),
|
localStore->printStorePath(path),
|
||||||
localStore->printStorePath(drvPath));
|
localStore->printStorePath(drvPath));
|
||||||
localStore->ensurePath(i.second.path);
|
localStore->ensurePath(path);
|
||||||
// FIXME: should copy directly from substituter to destStore.
|
// FIXME: should copy directly from substituter to destStore.
|
||||||
}
|
}
|
||||||
|
|
||||||
copyClosure(ref<Store>(localStore), destStore, {i.second.path});
|
copyClosure(ref<Store>(localStore), destStore, {path});
|
||||||
|
|
||||||
time_t stopTime = time(0);
|
time_t stopTime = time(0);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto mc = startDbUpdate();
|
auto mc = startDbUpdate();
|
||||||
pqxx::work txn(conn);
|
pqxx::work txn(conn);
|
||||||
createSubstitutionStep(txn, startTime, stopTime, build, drvPath, "out", i.second.path);
|
createSubstitutionStep(txn, startTime, stopTime, build, drvPath, "out", path);
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
printError("while copying/substituting output ‘%s’ of ‘%s’: %s",
|
printError("while copying/substituting output ‘%s’ of ‘%s’: %s",
|
||||||
localStore->printStorePath(i.second.path),
|
localStore->printStorePath(path),
|
||||||
localStore->printStorePath(drvPath),
|
localStore->printStorePath(drvPath),
|
||||||
e.what());
|
e.what());
|
||||||
valid = false;
|
valid = false;
|
||||||
|
@ -614,12 +617,12 @@ BuildOutput State::getBuildOutputCached(Connection & conn, nix::ref<nix::Store>
|
||||||
{
|
{
|
||||||
pqxx::work txn(conn);
|
pqxx::work txn(conn);
|
||||||
|
|
||||||
for (auto & output : drv.outputs) {
|
for (auto & output : drv.outputPaths(*localStore)) {
|
||||||
auto r = txn.exec_params
|
auto r = txn.exec_params
|
||||||
("select id, buildStatus, releaseName, closureSize, size from Builds b "
|
("select id, buildStatus, releaseName, closureSize, size from Builds b "
|
||||||
"join BuildOutputs o on b.id = o.build "
|
"join BuildOutputs o on b.id = o.build "
|
||||||
"where finished = 1 and (buildStatus = 0 or buildStatus = 6) and path = $1",
|
"where finished = 1 and (buildStatus = 0 or buildStatus = 6) and path = $1",
|
||||||
localStore->printStorePath(output.second.path));
|
localStore->printStorePath(output));
|
||||||
if (r.empty()) continue;
|
if (r.empty()) continue;
|
||||||
BuildID id = r[0][0].as<BuildID>();
|
BuildID id = r[0][0].as<BuildID>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue