Skip to content

Commit

Permalink
Add Store::buildPathsWithResults()
Browse files Browse the repository at this point in the history
This function is like buildPaths(), except that it returns a vector of
BuildResults containing the exact statuses and output paths of each
derivation / substitution. This is convenient for functions like
Installable::build(), because they then don't need to do another
series of calls to get the outputs of CA derivations. It's also a
precondition to impure derivations, where we *can't* query the output
of those derivations since they're not stored in the Nix database.

Note that PathSubstitutionGoal can now also return a BuildStatus.
  • Loading branch information
edolstra committed Mar 8, 2022
1 parent 92b8d4d commit 4e73a86
Show file tree
Hide file tree
Showing 17 changed files with 413 additions and 188 deletions.
33 changes: 26 additions & 7 deletions src/libcmd/installables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "eval-cache.hh"
#include "url.hh"
#include "registry.hh"
#include "build-result.hh"

#include <regex>
#include <queue>
Expand Down Expand Up @@ -769,8 +770,7 @@ BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPa
throw Error(
"the derivation '%s' doesn't have an output named '%s'",
store->printStorePath(bfd.drvPath), output);
if (settings.isExperimentalFeatureEnabled(
Xp::CaDerivations)) {
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
auto outputId =
DrvOutput{outputHashes.at(output), output};
auto realisation =
Expand Down Expand Up @@ -816,12 +816,31 @@ BuiltPaths Installable::build(
pathsToBuild.insert(pathsToBuild.end(), b.begin(), b.end());
}

if (mode == Realise::Nothing || mode == Realise::Derivation)
switch (mode) {
case Realise::Nothing:
case Realise::Derivation:
printMissing(store, pathsToBuild, lvlError);
else if (mode == Realise::Outputs)
store->buildPaths(pathsToBuild, bMode, evalStore);

return getBuiltPaths(evalStore, store, pathsToBuild);
return getBuiltPaths(evalStore, store, pathsToBuild);
case Realise::Outputs: {
BuiltPaths res;
for (auto & buildResult : store->buildPathsWithResults(pathsToBuild, bMode, evalStore)) {
if (!buildResult.success())
buildResult.rethrow();
if (buildResult.drvPath) {
std::map<std::string, StorePath> outputs;
for (auto & path : buildResult.builtOutputs)
outputs.emplace(path.first.outputName, path.second.outPath);
res.push_back(BuiltPath::Built{*buildResult.drvPath, outputs});
} else if (buildResult.outPath) {
res.push_back(BuiltPath::Opaque{*buildResult.outPath});
} else
abort();
}
return res;
}
default:
assert(false);
}
}

BuiltPaths Installable::toBuiltPaths(
Expand Down
14 changes: 13 additions & 1 deletion src/libstore/build-result.hh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct BuildResult
LogLimitExceeded,
NotDeterministic,
ResolvesToAlreadyValid,
NoSubstituters,
} status = MiscFailure;
std::string errorMsg;

Expand Down Expand Up @@ -63,15 +64,26 @@ struct BuildResult
non-determinism.) */
bool isNonDeterministic = false;

/* For derivations, the derivation path and the wanted outputs. */
std::optional<StorePath> drvPath;
DrvOutputs builtOutputs;

/* For substitutions, the substituted path. */
std::optional<StorePath> outPath;

/* The start/stop times of the build (or one of the rounds, if it
was repeated). */
time_t startTime = 0, stopTime = 0;

bool success() {
bool success()
{
return status == Built || status == Substituted || status == AlreadyValid || status == ResolvesToAlreadyValid;
}

void rethrow()
{
throw Error("%s", errorMsg);
}
};

}
Loading

0 comments on commit 4e73a86

Please sign in to comment.