Add a hook to run diffoscope when non-determinism is detected
This commit is contained in:
parent
b07060688a
commit
9a313469a4
2 changed files with 33 additions and 7 deletions
|
@ -2688,6 +2688,8 @@ void DerivationGoal::registerOutputs()
|
||||||
InodesSeen inodesSeen;
|
InodesSeen inodesSeen;
|
||||||
|
|
||||||
Path checkSuffix = "-check";
|
Path checkSuffix = "-check";
|
||||||
|
bool runDiffHook = settings.get("run-diff-hook", false);
|
||||||
|
bool keepPreviousRound = settings.keepFailed || runDiffHook;
|
||||||
|
|
||||||
/* Check whether the output paths were created, and grep each
|
/* Check whether the output paths were created, and grep each
|
||||||
output path to determine what other paths it references. Also make all
|
output path to determine what other paths it references. Also make all
|
||||||
|
@ -2919,33 +2921,56 @@ void DerivationGoal::registerOutputs()
|
||||||
if (!(*i == *j)) {
|
if (!(*i == *j)) {
|
||||||
result.isNonDeterministic = true;
|
result.isNonDeterministic = true;
|
||||||
Path prev = i->path + checkSuffix;
|
Path prev = i->path + checkSuffix;
|
||||||
auto msg = pathExists(prev)
|
bool prevExists = keepPreviousRound && pathExists(prev);
|
||||||
|
auto msg = prevExists
|
||||||
? fmt("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round", i->path, drvPath, prev)
|
? fmt("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round", i->path, drvPath, prev)
|
||||||
: fmt("output ‘%1%’ of ‘%2%’ differs from previous round", i->path, drvPath);
|
: fmt("output ‘%1%’ of ‘%2%’ differs from previous round", i->path, drvPath);
|
||||||
|
|
||||||
|
auto diffHook = settings.get("diff-hook", std::string(""));
|
||||||
|
if (prevExists && diffHook != "" && runDiffHook) {
|
||||||
|
try {
|
||||||
|
auto diff = runProgram(diffHook, true, {prev, i->path});
|
||||||
|
if (diff != "")
|
||||||
|
printError(chomp(diff));
|
||||||
|
} catch (Error & error) {
|
||||||
|
printError("diff hook execution failed: %s", error.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (settings.get("enforce-determinism", true))
|
if (settings.get("enforce-determinism", true))
|
||||||
throw NotDeterministic(msg);
|
throw NotDeterministic(msg);
|
||||||
|
|
||||||
printError(msg);
|
printError(msg);
|
||||||
curRound = nrRounds; // we know enough, bail out early
|
curRound = nrRounds; // we know enough, bail out early
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.keepFailed) {
|
/* If this is the first round of several, then move the output out
|
||||||
|
of the way. */
|
||||||
|
if (nrRounds > 1 && curRound == 1 && curRound < nrRounds && keepPreviousRound) {
|
||||||
for (auto & i : drv->outputs) {
|
for (auto & i : drv->outputs) {
|
||||||
Path prev = i.second.path + checkSuffix;
|
Path prev = i.second.path + checkSuffix;
|
||||||
deletePath(prev);
|
deletePath(prev);
|
||||||
if (curRound < nrRounds) {
|
|
||||||
Path dst = i.second.path + checkSuffix;
|
Path dst = i.second.path + checkSuffix;
|
||||||
if (rename(i.second.path.c_str(), dst.c_str()))
|
if (rename(i.second.path.c_str(), dst.c_str()))
|
||||||
throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst);
|
throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (curRound < nrRounds) {
|
if (curRound < nrRounds) {
|
||||||
prevInfos = infos;
|
prevInfos = infos;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove the -check directories if we're done. FIXME: keep them
|
||||||
|
if the result was not determistic? */
|
||||||
|
if (curRound == nrRounds) {
|
||||||
|
for (auto & i : drv->outputs) {
|
||||||
|
Path prev = i.second.path + checkSuffix;
|
||||||
|
deletePath(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Register each output path as valid, and register the sets of
|
/* Register each output path as valid, and register the sets of
|
||||||
paths referenced by each of them. If there are cycles in the
|
paths referenced by each of them. If there are cycles in the
|
||||||
outputs, this will fail. */
|
outputs, this will fail. */
|
||||||
|
|
|
@ -843,6 +843,7 @@ static void opServe(Strings opFlags, Strings opArgs)
|
||||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 3) {
|
if (GET_PROTOCOL_MINOR(clientVersion) >= 3) {
|
||||||
settings.set("build-repeat", std::to_string(readInt(in)));
|
settings.set("build-repeat", std::to_string(readInt(in)));
|
||||||
settings.set("enforce-determinism", readInt(in) != 0 ? "true" : "false");
|
settings.set("enforce-determinism", readInt(in) != 0 ? "true" : "false");
|
||||||
|
settings.set("run-diff-hook", "true");
|
||||||
}
|
}
|
||||||
settings.printRepeatedBuilds = false;
|
settings.printRepeatedBuilds = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue