Add a hook to run diffoscope when non-determinism is detected

This commit is contained in:
Eelco Dolstra 2016-12-07 17:57:35 +01:00
parent b07060688a
commit 9a313469a4
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
2 changed files with 33 additions and 7 deletions

View file

@ -2688,6 +2688,8 @@ void DerivationGoal::registerOutputs()
InodesSeen inodesSeen;
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
output path to determine what other paths it references. Also make all
@ -2919,25 +2921,39 @@ void DerivationGoal::registerOutputs()
if (!(*i == *j)) {
result.isNonDeterministic = true;
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 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))
throw NotDeterministic(msg);
printError(msg);
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) {
Path prev = i.second.path + checkSuffix;
deletePath(prev);
if (curRound < nrRounds) {
Path dst = i.second.path + checkSuffix;
if (rename(i.second.path.c_str(), dst.c_str()))
throw SysError(format("renaming %1% to %2%") % i.second.path % dst);
}
Path dst = i.second.path + checkSuffix;
if (rename(i.second.path.c_str(), dst.c_str()))
throw SysError(format("renaming %1% to %2%") % i.second.path % dst);
}
}
@ -2946,6 +2962,15 @@ void DerivationGoal::registerOutputs()
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
paths referenced by each of them. If there are cycles in the
outputs, this will fail. */

View file

@ -843,6 +843,7 @@ static void opServe(Strings opFlags, Strings opArgs)
if (GET_PROTOCOL_MINOR(clientVersion) >= 3) {
settings.set("build-repeat", std::to_string(readInt(in)));
settings.set("enforce-determinism", readInt(in) != 0 ? "true" : "false");
settings.set("run-diff-hook", "true");
}
settings.printRepeatedBuilds = false;
};