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; 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,25 +2921,39 @@ 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);
}
} }
} }
@ -2946,6 +2962,15 @@ void DerivationGoal::registerOutputs()
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. */

View file

@ -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;
}; };