diff --git a/src/libstore/build/derivation-building-goal.cc b/src/libstore/build/derivation-building-goal.cc index 3d6595012..e8df06564 100644 --- a/src/libstore/build/derivation-building-goal.cc +++ b/src/libstore/build/derivation-building-goal.cc @@ -119,7 +119,7 @@ void DerivationBuildingGoal::timedOut(Error && ex) killChild(); // We're not inside a coroutine, hence we can't use co_return here. // Thus we ignore the return value. - [[maybe_unused]] Done _ = done(BuildResult::TimedOut, {}, std::move(ex)); + [[maybe_unused]] Done _ = doneFailure({BuildResult::TimedOut, std::move(ex)}); } /** @@ -259,7 +259,7 @@ Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution() nrFailed, nrFailed == 1 ? "dependency" : "dependencies"); msg += showKnownOutputs(worker.store, *drv); - co_return done(BuildResult::DependencyFailed, {}, Error(msg)); + co_return doneFailure(BuildError(BuildResult::DependencyFailed, msg)); } /* Gather information necessary for computing the closure and/or @@ -360,9 +360,9 @@ Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution() auto resolvedResult = resolvedDrvGoal->buildResult; - SingleDrvOutputs builtOutputs; - if (resolvedResult.success()) { + SingleDrvOutputs builtOutputs; + auto resolvedHashes = staticOutputHashes(worker.store, drvResolved); StorePathSet outputPaths; @@ -412,13 +412,19 @@ Goal::Co DerivationBuildingGoal::gaveUpOnSubstitution() } runPostBuildHook(worker.store, *logger, drvPath, outputPaths); + + auto status = resolvedResult.status; + if (status == BuildResult::AlreadyValid) + status = BuildResult::ResolvesToAlreadyValid; + + co_return doneSuccess(status, std::move(builtOutputs)); + } else { + co_return doneFailure({ + BuildResult::DependencyFailed, + "build of resolved derivation '%s' failed", + worker.store.printStorePath(pathResolved), + }); } - - auto status = resolvedResult.status; - if (status == BuildResult::AlreadyValid) - status = BuildResult::ResolvesToAlreadyValid; - - co_return done(status, std::move(builtOutputs)); } /* If we get this far, we know no dynamic drvs inputs */ @@ -543,7 +549,7 @@ Goal::Co DerivationBuildingGoal::tryToBuild() debug("skipping build of derivation '%s', someone beat us to it", worker.store.printStorePath(drvPath)); outputLocks.setDeletion(true); outputLocks.unlock(); - co_return done(BuildResult::AlreadyValid, std::move(validOutputs)); + co_return doneSuccess(BuildResult::AlreadyValid, std::move(validOutputs)); } /* If any of the outputs already exist but are not valid, delete @@ -705,7 +711,7 @@ Goal::Co DerivationBuildingGoal::tryToBuild() } catch (BuildError & e) { outputLocks.unlock(); worker.permanentFailure = true; - co_return done(BuildResult::InputRejected, {}, std::move(e)); + co_return doneFailure(std::move(e)); } /* If we have to wait and retry (see below), then `builder` will @@ -752,7 +758,7 @@ Goal::Co DerivationBuildingGoal::tryToBuild() builder.reset(); outputLocks.unlock(); worker.permanentFailure = true; - co_return done(BuildResult::InputRejected, {}, std::move(e)); + co_return doneFailure(std::move(e)); // InputRejected } started(); @@ -764,7 +770,7 @@ Goal::Co DerivationBuildingGoal::tryToBuild() // N.B. cannot use `std::visit` with co-routine return if (auto * ste = std::get_if<0>(&res)) { outputLocks.unlock(); - co_return done(std::move(ste->first), {}, std::move(ste->second)); + co_return doneFailure(std::move(*ste)); } else if (auto * builtOutputs = std::get_if<1>(&res)) { StorePathSet outputPaths; for (auto & [_, output] : *builtOutputs) @@ -777,7 +783,7 @@ Goal::Co DerivationBuildingGoal::tryToBuild() (unlinked) lock files. */ outputLocks.setDeletion(true); outputLocks.unlock(); - co_return done(BuildResult::Built, std::move(*builtOutputs)); + co_return doneSuccess(BuildResult::Built, std::move(*builtOutputs)); } else { unreachable(); } @@ -922,7 +928,7 @@ Goal::Co DerivationBuildingGoal::hookDone() /* TODO (once again) support fine-grained error codes, see issue #12641. */ - co_return done(BuildResult::MiscFailure, {}, BuildError(msg)); + co_return doneFailure(BuildError{BuildResult::MiscFailure, msg}); } /* Compute the FS closure of the outputs and register them as @@ -949,7 +955,7 @@ Goal::Co DerivationBuildingGoal::hookDone() outputLocks.setDeletion(true); outputLocks.unlock(); - co_return done(BuildResult::Built, std::move(builtOutputs)); + co_return doneSuccess(BuildResult::Built, std::move(builtOutputs)); } HookReply DerivationBuildingGoal::tryBuildHook() @@ -1131,10 +1137,11 @@ void DerivationBuildingGoal::handleChildOutput(Descriptor fd, std::string_view d killChild(); // We're not inside a coroutine, hence we can't use co_return here. // Thus we ignore the return value. - [[maybe_unused]] Done _ = done( + [[maybe_unused]] Done _ = doneFailure(BuildError( BuildResult::LogLimitExceeded, - {}, - Error("%s killed after writing more than %d bytes of log output", getName(), settings.maxLogSize)); + "%s killed after writing more than %d bytes of log output", + getName(), + settings.maxLogSize)); return; } @@ -1295,13 +1302,27 @@ SingleDrvOutputs DerivationBuildingGoal::assertPathValidity() return validOutputs; } -Goal::Done -DerivationBuildingGoal::done(BuildResult::Status status, SingleDrvOutputs builtOutputs, std::optional ex) +Goal::Done DerivationBuildingGoal::doneSuccess(BuildResult::Status status, SingleDrvOutputs builtOutputs) { - outputLocks.unlock(); buildResult.status = status; - if (ex) - buildResult.errorMsg = fmt("%s", Uncolored(ex->info().msg)); + + assert(buildResult.success()); + + mcRunningBuilds.reset(); + + buildResult.builtOutputs = std::move(builtOutputs); + if (status == BuildResult::Built) + worker.doneBuilds++; + + worker.updateProgress(); + + return amDone(ecSuccess, std::nullopt); +} + +Goal::Done DerivationBuildingGoal::doneFailure(BuildError ex) +{ + buildResult.status = ex.status; + buildResult.errorMsg = fmt("%s", Uncolored(ex.info().msg)); if (buildResult.status == BuildResult::TimedOut) worker.timedOut = true; if (buildResult.status == BuildResult::PermanentFailure) @@ -1309,18 +1330,12 @@ DerivationBuildingGoal::done(BuildResult::Status status, SingleDrvOutputs builtO mcRunningBuilds.reset(); - if (buildResult.success()) { - buildResult.builtOutputs = std::move(builtOutputs); - if (status == BuildResult::Built) - worker.doneBuilds++; - } else { - if (status != BuildResult::DependencyFailed) - worker.failedBuilds++; - } + if (ex.status != BuildResult::DependencyFailed) + worker.failedBuilds++; worker.updateProgress(); - return amDone(buildResult.success() ? ecSuccess : ecFailed, std::move(ex)); + return amDone(ecFailed, {std::move(ex)}); } } // namespace nix diff --git a/src/libstore/build/derivation-check.cc b/src/libstore/build/derivation-check.cc index 7473380fa..c5b489b23 100644 --- a/src/libstore/build/derivation-check.cc +++ b/src/libstore/build/derivation-check.cc @@ -1,6 +1,7 @@ #include #include "nix/store/store-api.hh" +#include "nix/store/build-result.hh" #include "derivation-check.hh" @@ -54,6 +55,7 @@ void checkOutputs( auto applyChecks = [&](const DerivationOptions::OutputChecks & checks) { if (checks.maxSize && info.narSize > *checks.maxSize) throw BuildError( + BuildResult::OutputRejected, "path '%s' is too large at %d bytes; limit is %d bytes", store.printStorePath(info.path), info.narSize, @@ -63,6 +65,7 @@ void checkOutputs( uint64_t closureSize = getClosure(info.path).second; if (closureSize > *checks.maxClosureSize) throw BuildError( + BuildResult::OutputRejected, "closure of path '%s' is too large at %d bytes; limit is %d bytes", store.printStorePath(info.path), closureSize, @@ -83,6 +86,7 @@ void checkOutputs( std::string outputsListing = concatMapStringsSep(", ", outputs, [](auto & o) { return o.first; }); throw BuildError( + BuildResult::OutputRejected, "derivation '%s' output check for '%s' contains an illegal reference specifier '%s'," " expected store path or output name (one of [%s])", store.printStorePath(drvPath), @@ -115,6 +119,7 @@ void checkOutputs( badPathsStr += store.printStorePath(i); } throw BuildError( + BuildResult::OutputRejected, "output '%s' is not allowed to refer to the following paths:%s", store.printStorePath(info.path), badPathsStr); diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index dc28225b5..b9046744a 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -94,7 +94,7 @@ Goal::Co DerivationGoal::haveDerivation() /* If they are all valid, then we're done. */ if (checkResult && checkResult->second == PathStatus::Valid && buildMode == bmNormal) { - co_return done(BuildResult::AlreadyValid, checkResult->first); + co_return doneSuccess(BuildResult::AlreadyValid, checkResult->first); } Goals waitees; @@ -122,12 +122,10 @@ Goal::Co DerivationGoal::haveDerivation() assert(!drv->type().isImpure()); if (nrFailed > 0 && nrFailed > nrNoSubstituters && !settings.tryFallback) { - co_return done( + co_return doneFailure(BuildError( BuildResult::TransientFailure, - {}, - Error( - "some substitutes for the outputs of derivation '%s' failed (usually happens due to networking issues); try '--fallback' to build derivation from source ", - worker.store.printStorePath(drvPath))); + "some substitutes for the outputs of derivation '%s' failed (usually happens due to networking issues); try '--fallback' to build derivation from source ", + worker.store.printStorePath(drvPath))); } nrFailed = nrNoSubstituters = 0; @@ -137,7 +135,7 @@ Goal::Co DerivationGoal::haveDerivation() bool allValid = checkResult && checkResult->second == PathStatus::Valid; if (buildMode == bmNormal && allValid) { - co_return done(BuildResult::Substituted, checkResult->first); + co_return doneSuccess(BuildResult::Substituted, checkResult->first); } if (buildMode == bmRepair && allValid) { co_return repairClosure(); @@ -281,7 +279,7 @@ Goal::Co DerivationGoal::repairClosure() "some paths in the output closure of derivation '%s' could not be repaired", worker.store.printStorePath(drvPath)); } - co_return done(BuildResult::AlreadyValid, assertPathValidity()); + co_return doneSuccess(BuildResult::AlreadyValid, assertPathValidity()); } std::optional> DerivationGoal::checkPathValidity() @@ -339,12 +337,27 @@ Realisation DerivationGoal::assertPathValidity() return checkResult->first; } -Goal::Done -DerivationGoal::done(BuildResult::Status status, std::optional builtOutput, std::optional ex) +Goal::Done DerivationGoal::doneSuccess(BuildResult::Status status, Realisation builtOutput) { buildResult.status = status; - if (ex) - buildResult.errorMsg = fmt("%s", Uncolored(ex->info().msg)); + + assert(buildResult.success()); + + mcExpectedBuilds.reset(); + + buildResult.builtOutputs = {{wantedOutput, std::move(builtOutput)}}; + if (status == BuildResult::Built) + worker.doneBuilds++; + + worker.updateProgress(); + + return amDone(ecSuccess, std::nullopt); +} + +Goal::Done DerivationGoal::doneFailure(BuildError ex) +{ + buildResult.status = ex.status; + buildResult.errorMsg = fmt("%s", Uncolored(ex.info().msg)); if (buildResult.status == BuildResult::TimedOut) worker.timedOut = true; if (buildResult.status == BuildResult::PermanentFailure) @@ -352,19 +365,12 @@ DerivationGoal::done(BuildResult::Status status, std::optional buil mcExpectedBuilds.reset(); - if (buildResult.success()) { - assert(builtOutput); - buildResult.builtOutputs = {{wantedOutput, std::move(*builtOutput)}}; - if (status == BuildResult::Built) - worker.doneBuilds++; - } else { - if (status != BuildResult::DependencyFailed) - worker.failedBuilds++; - } + if (ex.status != BuildResult::DependencyFailed) + worker.failedBuilds++; worker.updateProgress(); - return amDone(buildResult.success() ? ecSuccess : ecFailed, std::move(ex)); + return amDone(ecFailed, {std::move(ex)}); } } // namespace nix diff --git a/src/libstore/derivation-options.cc b/src/libstore/derivation-options.cc index 1acb9dc03..630159629 100644 --- a/src/libstore/derivation-options.cc +++ b/src/libstore/derivation-options.cc @@ -265,7 +265,8 @@ DerivationOptions::getParsedExportReferencesGraph(const StoreDirConfig & store) StorePathSet storePaths; for (auto & storePathS : ss) { if (!store.isInStore(storePathS)) - throw BuildError("'exportReferencesGraph' contains a non-store path '%1%'", storePathS); + throw BuildError( + BuildResult::InputRejected, "'exportReferencesGraph' contains a non-store path '%1%'", storePathS); storePaths.insert(store.toStorePath(storePathS).first); } res.insert_or_assign(fileName, storePaths); diff --git a/src/libstore/include/nix/store/build-result.hh b/src/libstore/include/nix/store/build-result.hh index 58138ed45..a743aa387 100644 --- a/src/libstore/include/nix/store/build-result.hh +++ b/src/libstore/include/nix/store/build-result.hh @@ -1,13 +1,13 @@ #pragma once ///@file -#include "nix/store/realisation.hh" -#include "nix/store/derived-path.hh" - #include #include #include +#include "nix/store/derived-path.hh" +#include "nix/store/realisation.hh" + namespace nix { struct BuildResult @@ -90,6 +90,26 @@ struct BuildResult } }; +/** + * denotes a permanent build failure + */ +struct BuildError : public Error +{ + BuildResult::Status status; + + BuildError(BuildResult::Status status, BuildError && error) + : Error{std::move(error)} + , status{status} + { + } + + BuildError(BuildResult::Status status, auto &&... args) + : Error{args...} + , status{status} + { + } +}; + /** * A `BuildResult` together with its "primary key". */ diff --git a/src/libstore/include/nix/store/build/derivation-builder.hh b/src/libstore/include/nix/store/build/derivation-builder.hh index 94a3ffae8..c4f709456 100644 --- a/src/libstore/include/nix/store/build/derivation-builder.hh +++ b/src/libstore/include/nix/store/build/derivation-builder.hh @@ -165,7 +165,7 @@ struct DerivationBuilder : RestrictionContext * more information. The second case indicates success, and * realisations for each output of the derivation are returned. */ - virtual std::variant, SingleDrvOutputs> unprepareBuild() = 0; + virtual std::variant unprepareBuild() = 0; /** * Stop the in-process nix daemon thread. diff --git a/src/libstore/include/nix/store/build/derivation-building-goal.hh b/src/libstore/include/nix/store/build/derivation-building-goal.hh index 95949649c..38f0fc7bf 100644 --- a/src/libstore/include/nix/store/build/derivation-building-goal.hh +++ b/src/libstore/include/nix/store/build/derivation-building-goal.hh @@ -170,7 +170,9 @@ struct DerivationBuildingGoal : public Goal void started(); - Done done(BuildResult::Status status, SingleDrvOutputs builtOutputs = {}, std::optional ex = {}); + Done doneSuccess(BuildResult::Status status, SingleDrvOutputs builtOutputs); + + Done doneFailure(BuildError ex); void appendLogTailErrorMsg(std::string & msg); diff --git a/src/libstore/include/nix/store/build/derivation-goal.hh b/src/libstore/include/nix/store/build/derivation-goal.hh index d9042d136..85b471e28 100644 --- a/src/libstore/include/nix/store/build/derivation-goal.hh +++ b/src/libstore/include/nix/store/build/derivation-goal.hh @@ -99,13 +99,9 @@ private: Co repairClosure(); - /** - * @param builtOutput Must be set if `status` is successful. - */ - Done done( - BuildResult::Status status, - std::optional builtOutput = std::nullopt, - std::optional ex = {}); + Done doneSuccess(BuildResult::Status status, Realisation builtOutput); + + Done doneFailure(BuildError ex); }; } // namespace nix diff --git a/src/libstore/include/nix/store/store-api.hh b/src/libstore/include/nix/store/store-api.hh index 987ed4d48..7d019ea21 100644 --- a/src/libstore/include/nix/store/store-api.hh +++ b/src/libstore/include/nix/store/store-api.hh @@ -24,11 +24,6 @@ namespace nix { -MakeError(SubstError, Error); -/** - * denotes a permanent build failure - */ -MakeError(BuildError, Error); MakeError(InvalidPath, Error); MakeError(Unsupported, Error); MakeError(SubstituteGone, Error); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index a66a97866..7872d4f93 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1002,7 +1002,10 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos) }}, {[&](const StorePath & path, const StorePath & parent) { return BuildError( - "cycle detected in the references of '%s' from '%s'", printStorePath(path), printStorePath(parent)); + BuildResult::OutputRejected, + "cycle detected in the references of '%s' from '%s'", + printStorePath(path), + printStorePath(parent)); }}); txn.commit(); diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index c794f8d06..8de41fe19 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -322,7 +322,10 @@ StorePaths Store::topoSortPaths(const StorePathSet & paths) }}, {[&](const StorePath & path, const StorePath & parent) { return BuildError( - "cycle detected in the references of '%s' from '%s'", printStorePath(path), printStorePath(parent)); + BuildResult::OutputRejected, + "cycle detected in the references of '%s' from '%s'", + printStorePath(path), + printStorePath(parent)); }}); } diff --git a/src/libstore/posix-fs-canonicalise.cc b/src/libstore/posix-fs-canonicalise.cc index a889938c9..b6a64e65b 100644 --- a/src/libstore/posix-fs-canonicalise.cc +++ b/src/libstore/posix-fs-canonicalise.cc @@ -98,7 +98,7 @@ static void canonicalisePathMetaData_( (i.e. "touch $out/foo; ln $out/foo $out/bar"). */ if (uidRange && (st.st_uid < uidRange->first || st.st_uid > uidRange->second)) { if (S_ISDIR(st.st_mode) || !inodesSeen.count(Inode(st.st_dev, st.st_ino))) - throw BuildError("invalid ownership on file '%1%'", path); + throw BuildError(BuildResult::OutputRejected, "invalid ownership on file '%1%'", path); mode_t mode = st.st_mode & ~S_IFMT; assert( S_ISLNK(st.st_mode) diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index fad79a83e..d96be5965 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -770,6 +770,7 @@ StorePathSet Store::exportReferences(const StorePathSet & storePaths, const Stor for (auto & storePath : storePaths) { if (!inputPaths.count(storePath)) throw BuildError( + BuildResult::InputRejected, "cannot export references of path '%s' because it is not in the input closure of the derivation", printStorePath(storePath)); diff --git a/src/libstore/unix/build/derivation-builder.cc b/src/libstore/unix/build/derivation-builder.cc index 3140c716d..0de12badc 100644 --- a/src/libstore/unix/build/derivation-builder.cc +++ b/src/libstore/unix/build/derivation-builder.cc @@ -47,7 +47,13 @@ namespace nix { -MakeError(NotDeterministic, BuildError); +struct NotDeterministic : BuildError +{ + NotDeterministic(auto &&... args) + : BuildError(BuildResult::NotDeterministic, args...) + { + } +}; /** * This class represents the state for building locally. @@ -186,7 +192,7 @@ public: void startBuilder() override; - std::variant, SingleDrvOutputs> unprepareBuild() override; + std::variant unprepareBuild() override; protected: @@ -421,7 +427,7 @@ bool DerivationBuilderImpl::prepareBuild() return true; } -std::variant, SingleDrvOutputs> DerivationBuilderImpl::unprepareBuild() +std::variant DerivationBuilderImpl::unprepareBuild() { // FIXME: get rid of this, rely on RAII. Finally releaseBuildUser([&]() { @@ -494,7 +500,10 @@ std::variant, SingleDrvOutputs> Derivation if (diskFull) msg += "\nnote: build failure may have been caused by lack of free disk space"; - throw BuildError(msg); + throw BuildError( + !derivationType.isSandboxed() || diskFull ? BuildResult::TransientFailure + : BuildResult::PermanentFailure, + msg); } /* Compute the FS closure of the outputs and register them as @@ -510,12 +519,7 @@ std::variant, SingleDrvOutputs> Derivation return std::move(builtOutputs); } catch (BuildError & e) { - BuildResult::Status st = dynamic_cast(&e) ? BuildResult::NotDeterministic - : statusOk(status) ? BuildResult::OutputRejected - : !derivationType.isSandboxed() || diskFull ? BuildResult::TransientFailure - : BuildResult::PermanentFailure; - - return std::pair{std::move(st), std::move(e)}; + return std::move(e); } } @@ -683,7 +687,7 @@ void DerivationBuilderImpl::startBuilder() fmt("\nNote: run `%s` to run programs for x86_64-darwin", Magenta("/usr/sbin/softwareupdate --install-rosetta && launchctl stop org.nixos.nix-daemon")); - throw BuildError(msg); + throw BuildError(BuildResult::InputRejected, msg); } auto buildDir = store.config->getBuildDir(); @@ -1373,6 +1377,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() auto optSt = maybeLstat(actualPath.c_str()); if (!optSt) throw BuildError( + BuildResult::OutputRejected, "builder for '%s' failed to produce output path for output '%s' at '%s'", store.printStorePath(drvPath), outputName, @@ -1387,6 +1392,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) || (buildUser && st.st_uid != buildUser->getUID())) throw BuildError( + BuildResult::OutputRejected, "suspicious ownership or permission on '%s' for output '%s'; rejecting this build output", actualPath, outputName); @@ -1423,7 +1429,11 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() {[&](const std::string & name) { auto orifu = get(outputReferencesIfUnregistered, name); if (!orifu) - throw BuildError("no output reference for '%s' in build of '%s'", name, store.printStorePath(drvPath)); + throw BuildError( + BuildResult::OutputRejected, + "no output reference for '%s' in build of '%s'", + name, + store.printStorePath(drvPath)); return std::visit( overloaded{ /* Since we'll use the already installed versions of these, we @@ -1445,6 +1455,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() {[&](const std::string & path, const std::string & parent) { // TODO with more -vvvv also show the temporary paths for manual inspection. return BuildError( + BuildResult::OutputRejected, "cycle detected in build of '%s' in the references of output '%s' from output '%s'", store.printStorePath(drvPath), path, @@ -1538,11 +1549,12 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() auto newInfoFromCA = [&](const DerivationOutput::CAFloating outputHash) -> ValidPathInfo { auto st = get(outputStats, outputName); if (!st) - throw BuildError("output path %1% without valid stats info", actualPath); + throw BuildError(BuildResult::OutputRejected, "output path %1% without valid stats info", actualPath); if (outputHash.method.getFileIngestionMethod() == FileIngestionMethod::Flat) { /* The output path should be a regular file without execute permission. */ if (!S_ISREG(st->st_mode) || (st->st_mode & S_IXUSR) != 0) throw BuildError( + BuildResult::OutputRejected, "output path '%1%' should be a non-executable regular file " "since recursive hashing is not enabled (one of outputHashMode={flat,text} is true)", actualPath); @@ -1644,6 +1656,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() valid. */ miscMethods->noteHashMismatch(); delayedException = std::make_exception_ptr(BuildError( + BuildResult::OutputRejected, "hash mismatch in fixed-output derivation '%s':\n specified: %s\n got: %s", store.printStorePath(drvPath), wanted.to_string(HashFormat::SRI, true), @@ -1652,6 +1665,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() if (!newInfo0.references.empty()) { auto numViolations = newInfo.references.size(); delayedException = std::make_exception_ptr(BuildError( + BuildResult::OutputRejected, "fixed-output derivations must not reference store paths: '%s' references %d distinct paths, e.g. '%s'", store.printStorePath(drvPath), numViolations, diff --git a/src/libstore/unix/build/linux-derivation-builder.cc b/src/libstore/unix/build/linux-derivation-builder.cc index b92d05607..39b8f09ae 100644 --- a/src/libstore/unix/build/linux-derivation-builder.cc +++ b/src/libstore/unix/build/linux-derivation-builder.cc @@ -659,7 +659,7 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu throw SysError("setuid failed"); } - std::variant, SingleDrvOutputs> unprepareBuild() override + std::variant unprepareBuild() override { sandboxMountNamespace = -1; sandboxUserNamespace = -1; diff --git a/tests/functional/dyn-drv/failing-outer.sh b/tests/functional/dyn-drv/failing-outer.sh index 3feda74fb..596efe43d 100644 --- a/tests/functional/dyn-drv/failing-outer.sh +++ b/tests/functional/dyn-drv/failing-outer.sh @@ -9,4 +9,4 @@ expected=100 if [[ -v NIX_DAEMON_PACKAGE ]]; then expected=1; fi # work around the daemon not returning a 100 status correctly expectStderr "$expected" nix-build ./text-hashed-output.nix -A failingWrapper --no-out-link \ - | grepQuiet "build of '.*use-dynamic-drv-in-non-dynamic-drv-wrong.drv' failed" + | grepQuiet "build of resolved derivation '.*use-dynamic-drv-in-non-dynamic-drv-wrong.drv' failed"