forked from lix-project/lix
nix3-build: show all FOD errors with --keep-going
Basically I'd expect the same behavior as with `nix-build`, i.e.
with `--keep-going` the hash-mismatch error of each failing
fixed-output derivation is shown.
The approach is derived from `Store::buildPaths` (`entry-point.cc`):
instead of throwing the first build-result, check if there are any build
errors and if so, display all of them and throw after that.
Unfortunately, the BuildResult struct doesn't have an `ErrorInfo`
(there's a FIXME for that at least), so I have to construct my own here.
This is a rather cheap bugfix and I decided against touching too many
parts of libstore for that (also I don't know if that's in line with the
ongoing refactoring work).
Closes lix-project/lix#302
Change-Id: I378ab984fa271e6808c6897c45e0f070eb4c6fac
This commit is contained in:
parent
f6dc40cd1c
commit
e146393183
6
doc/manual/rl-next/consistent-nix-build.md
Normal file
6
doc/manual/rl-next/consistent-nix-build.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
synopsis: Show all FOD errors with `nix build --keep-going`
|
||||||
|
---
|
||||||
|
|
||||||
|
`nix build --keep-going` now behaves consistently with `nix-build --keep-going`. This means
|
||||||
|
that if e.g. multiple FODs fail to build, all hash mismatches are displayed.
|
|
@ -547,6 +547,37 @@ std::vector<BuiltPathWithResult> Installable::build(
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void throwBuildErrors(
|
||||||
|
std::vector<KeyedBuildResult> & buildResults,
|
||||||
|
const Store & store)
|
||||||
|
{
|
||||||
|
std::vector<KeyedBuildResult> failed;
|
||||||
|
for (auto & buildResult : buildResults) {
|
||||||
|
if (!buildResult.success()) {
|
||||||
|
failed.push_back(buildResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto failedResult = failed.begin();
|
||||||
|
if (failedResult != failed.end()) {
|
||||||
|
if (failed.size() == 1) {
|
||||||
|
failedResult->rethrow();
|
||||||
|
} else {
|
||||||
|
StringSet failedPaths;
|
||||||
|
for (; failedResult != failed.end(); failedResult++) {
|
||||||
|
if (!failedResult->errorMsg.empty()) {
|
||||||
|
logError(ErrorInfo{
|
||||||
|
.level = lvlError,
|
||||||
|
.msg = failedResult->errorMsg,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
failedPaths.insert(failedResult->path.to_string(store));
|
||||||
|
}
|
||||||
|
throw Error("build of %s failed", concatStringsSep(", ", quoteStrings(failedPaths)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build2(
|
std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build2(
|
||||||
ref<Store> evalStore,
|
ref<Store> evalStore,
|
||||||
ref<Store> store,
|
ref<Store> store,
|
||||||
|
@ -608,10 +639,9 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build
|
||||||
if (settings.printMissing)
|
if (settings.printMissing)
|
||||||
printMissing(store, pathsToBuild, lvlInfo);
|
printMissing(store, pathsToBuild, lvlInfo);
|
||||||
|
|
||||||
for (auto & buildResult : store->buildPathsWithResults(pathsToBuild, bMode, evalStore)) {
|
auto buildResults = store->buildPathsWithResults(pathsToBuild, bMode, evalStore);
|
||||||
if (!buildResult.success())
|
throwBuildErrors(buildResults, *store);
|
||||||
buildResult.rethrow();
|
for (auto & buildResult : buildResults) {
|
||||||
|
|
||||||
for (auto & aux : backmap[buildResult.path]) {
|
for (auto & aux : backmap[buildResult.path]) {
|
||||||
std::visit(overloaded {
|
std::visit(overloaded {
|
||||||
[&](const DerivedPath::Built & bfd) {
|
[&](const DerivedPath::Built & bfd) {
|
||||||
|
|
|
@ -133,3 +133,35 @@ nix build --impure -f multiple-outputs.nix --json e --no-link | jq --exit-status
|
||||||
# Make sure that `--stdin` works and does not apply any defaults
|
# Make sure that `--stdin` works and does not apply any defaults
|
||||||
printf "" | nix build --no-link --stdin --json | jq --exit-status '. == []'
|
printf "" | nix build --no-link --stdin --json | jq --exit-status '. == []'
|
||||||
printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status '.[0]|has("drvPath")'
|
printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status '.[0]|has("drvPath")'
|
||||||
|
|
||||||
|
# --keep-going and FOD
|
||||||
|
out="$(nix build -f fod-failing.nix -L 2>&1)" && status=0 || status=$?
|
||||||
|
test "$status" = 1
|
||||||
|
# one "hash mismatch" error, one "build of ... failed"
|
||||||
|
test "$(<<<"$out" grep -E '^error:' | wc -l)" = 2
|
||||||
|
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'"
|
||||||
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
|
||||||
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
||||||
|
<<<"$out" grepQuiet -E "error: build of '.*-x[1-4]\\.drv\\^out', '.*-x[1-4]\\.drv\\^out', '.*-x[1-4]\\.drv\\^out', '.*-x[1-4]\\.drv\\^out' failed"
|
||||||
|
|
||||||
|
out="$(nix build -f fod-failing.nix -L x1 x2 x3 --keep-going 2>&1)" && status=0 || status=$?
|
||||||
|
test "$status" = 1
|
||||||
|
# three "hash mismatch" errors - for each failing fod, one "build of ... failed"
|
||||||
|
test "$(<<<"$out" grep -E '^error:' | wc -l)" = 4
|
||||||
|
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'"
|
||||||
|
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
|
||||||
|
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
||||||
|
<<<"$out" grepQuiet -E "error: build of '.*-x[1-3]\\.drv\\^out', '.*-x[1-3]\\.drv\\^out', '.*-x[1-3]\\.drv\\^out' failed"
|
||||||
|
|
||||||
|
out="$(nix build -f fod-failing.nix -L x4 2>&1)" && status=0 || status=$?
|
||||||
|
test "$status" = 1
|
||||||
|
test "$(<<<"$out" grep -E '^error:' | wc -l)" = 2
|
||||||
|
<<<"$out" grepQuiet -E "error: 1 dependencies of derivation '.*-x4\\.drv' failed to build"
|
||||||
|
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
||||||
|
|
||||||
|
out="$(nix build -f fod-failing.nix -L x4 --keep-going 2>&1)" && status=0 || status=$?
|
||||||
|
test "$status" = 1
|
||||||
|
test "$(<<<"$out" grep -E '^error:' | wc -l)" = 3
|
||||||
|
<<<"$out" grepQuiet -E "error: 2 dependencies of derivation '.*-x4\\.drv' failed to build"
|
||||||
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
|
||||||
|
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
|
||||||
|
|
39
tests/functional/fod-failing.nix
Normal file
39
tests/functional/fod-failing.nix
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
with import ./config.nix;
|
||||||
|
rec {
|
||||||
|
x1 = mkDerivation {
|
||||||
|
name = "x1";
|
||||||
|
builder = builtins.toFile "builder.sh"
|
||||||
|
''
|
||||||
|
echo $name > $out
|
||||||
|
'';
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||||
|
};
|
||||||
|
x2 = mkDerivation {
|
||||||
|
name = "x2";
|
||||||
|
builder = builtins.toFile "builder.sh"
|
||||||
|
''
|
||||||
|
echo $name > $out
|
||||||
|
'';
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||||
|
};
|
||||||
|
x3 = mkDerivation {
|
||||||
|
name = "x3";
|
||||||
|
builder = builtins.toFile "builder.sh"
|
||||||
|
''
|
||||||
|
echo $name > $out
|
||||||
|
'';
|
||||||
|
outputHashMode = "recursive";
|
||||||
|
outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||||
|
};
|
||||||
|
x4 = mkDerivation {
|
||||||
|
name = "x4";
|
||||||
|
inherit x2 x3;
|
||||||
|
builder = builtins.toFile "builder.sh"
|
||||||
|
''
|
||||||
|
echo $x2 $x3
|
||||||
|
exit 1
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue