Skip to content

Commit ee75a66

Browse files
committed
Installable::build(): Report succeeding/failing installables
If any installable fails to build, it will print something like ✅ flake:nixpkgs#hello ❌ git+file:///home/eelco/Dev/patchelf#packages.x86_64-linux.default error: Cannot build '/nix/store/nh2dx9cqcy9lw4d4rvd0dbsflwdsbzdy-patchelf-0.18.0.drv'. Reason: builder failed with exit code 2. ... ❓ git+file:///home/eelco/Dev/patchelf#hydraJobs.coverage (cancelled) It doesn't print anything if all installables succeed.
1 parent c6d07c4 commit ee75a66

File tree

4 files changed

+61
-44
lines changed

4 files changed

+61
-44
lines changed

src/libcmd/include/nix/cmd/installables.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ struct Installable
183183
const Installables & installables,
184184
BuildMode bMode = bmNormal);
185185

186+
static void throwBuildErrors(std::vector<InstallableWithBuildResult> & buildResults, const Store & store);
187+
186188
static std::set<StorePath> toStorePathSet(
187189
ref<Store> evalStore, ref<Store> store, Realise mode, OperateOn operateOn, const Installables & installables);
188190

src/libcmd/installables.cc

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "nix/util/url.hh"
2222
#include "nix/fetchers/registry.hh"
2323
#include "nix/store/build-result.hh"
24+
#include "nix/util/exit.hh"
2425

2526
#include <regex>
2627
#include <queue>
@@ -600,45 +601,54 @@ const BuiltPathWithResult & InstallableWithBuildResult::getSuccess() const
600601
return *std::get_if<Success>(&result);
601602
}
602603

603-
std::vector<BuiltPathWithResult> Installable::build(
604-
ref<Store> evalStore, ref<Store> store, Realise mode, const Installables & installables, BuildMode bMode)
604+
void Installable::throwBuildErrors(std::vector<InstallableWithBuildResult> & buildResults, const Store & store)
605605
{
606-
std::vector<BuiltPathWithResult> res;
607-
for (auto & b : build2(evalStore, store, mode, installables, bMode))
608-
res.push_back(b.getSuccess());
609-
return res;
610-
}
611-
612-
static void throwBuildErrors(std::vector<KeyedBuildResult> & buildResults, const Store & store)
613-
{
614-
std::vector<std::pair<const KeyedBuildResult *, const KeyedBuildResult::Failure *>> failed;
615606
for (auto & buildResult : buildResults) {
616-
if (auto * failure = buildResult.tryGetFailure()) {
617-
failed.push_back({&buildResult, failure});
618-
}
619-
}
607+
if (std::get_if<InstallableWithBuildResult::Failure>(&buildResult.result)) {
608+
// Report success first.
609+
for (auto & buildResult : buildResults) {
610+
if (std::get_if<InstallableWithBuildResult::Success>(&buildResult.result))
611+
notice("" ANSI_BOLD "%s" ANSI_NORMAL, buildResult.installable->what());
612+
}
620613

621-
auto failedResult = failed.begin();
622-
if (failedResult != failed.end()) {
623-
if (failed.size() == 1) {
624-
failedResult->second->rethrow();
625-
} else {
626-
StringSet failedPaths;
627-
for (; failedResult != failed.end(); failedResult++) {
628-
if (!failedResult->second->errorMsg.empty()) {
629-
logError(
630-
ErrorInfo{
631-
.level = lvlError,
632-
.msg = failedResult->second->errorMsg,
633-
});
614+
// Then failures.
615+
for (auto & buildResult : buildResults) {
616+
if (auto failure = std::get_if<InstallableWithBuildResult::Failure>(&buildResult.result)) {
617+
auto failure2 = failure->tryGetFailure();
618+
assert(failure2);
619+
if (failure2->status == BuildResult::Failure::Cancelled
620+
// FIXME: remove MiscFailure eventually
621+
|| failure2->status == BuildResult::Failure::MiscFailure)
622+
notice(
623+
"" ANSI_BOLD "%s" ANSI_NORMAL ANSI_FAINT " (cancelled)",
624+
buildResult.installable->what());
625+
else {
626+
printError("" ANSI_RED "%s" ANSI_NORMAL, buildResult.installable->what());
627+
try {
628+
failure2->rethrow();
629+
} catch (Error & e) {
630+
logError(e.info());
631+
}
632+
}
634633
}
635-
failedPaths.insert(failedResult->first->path.to_string(store));
636634
}
637-
throw Error("build of %s failed", concatStringsSep(", ", quoteStrings(failedPaths)));
635+
636+
throw Exit(1);
638637
}
639638
}
640639
}
641640

641+
std::vector<BuiltPathWithResult> Installable::build(
642+
ref<Store> evalStore, ref<Store> store, Realise mode, const Installables & installables, BuildMode bMode)
643+
{
644+
auto results = build2(evalStore, store, mode, installables, bMode);
645+
throwBuildErrors(results, *store);
646+
std::vector<BuiltPathWithResult> res;
647+
for (auto & b : results)
648+
res.push_back(b.getSuccess());
649+
return res;
650+
}
651+
642652
std::vector<InstallableWithBuildResult> Installable::build2(
643653
ref<Store> evalStore, ref<Store> store, Realise mode, const Installables & installables, BuildMode bMode)
644654
{
@@ -704,9 +714,13 @@ std::vector<InstallableWithBuildResult> Installable::build2(
704714
printMissing(store, pathsToBuild, lvlInfo);
705715

706716
auto buildResults = store->buildPathsWithResults(pathsToBuild, bMode, evalStore);
707-
throwBuildErrors(buildResults, *store);
708717
for (auto & buildResult : buildResults) {
709-
// If we didn't throw, they must all be successes.
718+
if (buildResult.tryGetFailure()) {
719+
for (auto & aux : backmap[buildResult.path]) {
720+
res.push_back({.installable = aux.installable, .result = buildResult});
721+
}
722+
continue;
723+
}
710724
auto & success = std::get<nix::BuildResult::Success>(buildResult.inner);
711725
for (auto & aux : backmap[buildResult.path]) {
712726
std::visit(

src/nix/profile.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,10 @@ struct CmdProfileAdd : InstallablesCommand, MixDefaultProfile
364364
{
365365
ProfileManifest manifest(*getEvalState(), *profile);
366366

367-
auto builtPaths = builtPathsPerInstallable(
368-
Installable::build2(getEvalStore(), store, Realise::Outputs, installables, bmNormal));
367+
auto buildResults = Installable::build2(getEvalStore(), store, Realise::Outputs, installables, bmNormal);
368+
Installable::throwBuildErrors(buildResults, *store);
369+
370+
auto builtPaths = builtPathsPerInstallable(buildResults);
369371

370372
for (auto & installable : installables) {
371373
ProfileElement element;
@@ -767,8 +769,10 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
767769
return;
768770
}
769771

770-
auto builtPaths = builtPathsPerInstallable(
771-
Installable::build2(getEvalStore(), store, Realise::Outputs, installables, bmNormal));
772+
auto buildResults = Installable::build2(getEvalStore(), store, Realise::Outputs, installables, bmNormal);
773+
Installable::throwBuildErrors(buildResults, *store);
774+
775+
auto builtPaths = builtPathsPerInstallable(buildResults);
772776

773777
for (size_t i = 0; i < installables.size(); ++i) {
774778
auto & installable = installables.at(i);

tests/functional/build.sh

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,20 +161,17 @@ printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status '
161161
out="$(nix build -f fod-failing.nix -L 2>&1)" && status=0 || status=$?
162162
test "$status" = 1
163163
# one "hash mismatch" error, one "build of ... failed"
164-
test "$(<<<"$out" grep -cE '^error:')" = 2
165-
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'"
166-
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
167-
<<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
168-
<<<"$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"
164+
test "$(<<<"$out" grep -cE '^error:')" = 1
165+
test "$(<<<"$out" grep -cE '(cancelled)')" = 3
166+
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation"
169167

170168
out="$(nix build -f fod-failing.nix -L x1 x2 x3 --keep-going 2>&1)" && status=0 || status=$?
171169
test "$status" = 1
172-
# three "hash mismatch" errors - for each failing fod, one "build of ... failed"
173-
test "$(<<<"$out" grep -cE '^error:')" = 4
170+
# three "hash mismatch" errors - for each failing fod
171+
test "$(<<<"$out" grep -cE '^error:')" = 3
174172
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'"
175173
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x3\\.drv'"
176174
<<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x2\\.drv'"
177-
<<<"$out" grepQuiet -E "error: build of '.*-x[1-3]\\.drv\\^out', '.*-x[1-3]\\.drv\\^out', '.*-x[1-3]\\.drv\\^out' failed"
178175

179176
out="$(nix build -f fod-failing.nix -L x4 2>&1)" && status=0 || status=$?
180177
test "$status" = 1

0 commit comments

Comments
 (0)