aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/derivations.cc
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-03-01 16:57:36 -0500
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-04-07 08:34:58 -0400
commit4e9f32f993aaa9f7995919e480e0e920d946184d (patch)
treed8947a5032185b7e9ecbfb5e2740a784416a7155 /src/libstore/derivations.cc
parentb200784cec056da53378eb043cae4fad188e4e6f (diff)
Liberate `checkDerivationOutputs` from `LocalStore`
Make it instead a method on `Derivation` that can work with any store. We will need this for a CLI command to create a derivation.
Diffstat (limited to 'src/libstore/derivations.cc')
-rw-r--r--src/libstore/derivations.cc60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index 9f74f1c30..abdfb1978 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -890,6 +890,66 @@ std::optional<BasicDerivation> Derivation::tryResolve(
}
+void Derivation::checkInvariants(Store & store, const StorePath & drvPath) const
+{
+ assert(drvPath.isDerivation());
+ std::string drvName(drvPath.name());
+ drvName = drvName.substr(0, drvName.size() - drvExtension.size());
+
+ if (drvName != name) {
+ throw Error("Derivation '%s' has name '%s' which does not match its path", store.printStorePath(drvPath), name);
+ }
+
+ auto envHasRightPath = [&](const StorePath & actual, const std::string & varName)
+ {
+ auto j = env.find(varName);
+ if (j == env.end() || store.parseStorePath(j->second) != actual)
+ throw Error("derivation '%s' has incorrect environment variable '%s', should be '%s'",
+ store.printStorePath(drvPath), varName, store.printStorePath(actual));
+ };
+
+
+ // Don't need the answer, but do this anyways to assert is proper
+ // combination. The code below is more general and naturally allows
+ // combinations that are currently prohibited.
+ type();
+
+ std::optional<DrvHash> hashesModulo;
+ for (auto & i : outputs) {
+ std::visit(overloaded {
+ [&](const DerivationOutput::InputAddressed & doia) {
+ if (!hashesModulo) {
+ // somewhat expensive so we do lazily
+ hashesModulo = hashDerivationModulo(store, *this, true);
+ }
+ auto currentOutputHash = get(hashesModulo->hashes, i.first);
+ if (!currentOutputHash)
+ throw Error("derivation '%s' has unexpected output '%s' (local-store / hashesModulo) named '%s'",
+ store.printStorePath(drvPath), store.printStorePath(doia.path), i.first);
+ StorePath recomputed = store.makeOutputPath(i.first, *currentOutputHash, drvName);
+ if (doia.path != recomputed)
+ throw Error("derivation '%s' has incorrect output '%s', should be '%s'",
+ store.printStorePath(drvPath), store.printStorePath(doia.path), store.printStorePath(recomputed));
+ envHasRightPath(doia.path, i.first);
+ },
+ [&](const DerivationOutput::CAFixed & dof) {
+ StorePath path = store.makeFixedOutputPath(dof.hash.method, dof.hash.hash, drvName);
+ envHasRightPath(path, i.first);
+ },
+ [&](const DerivationOutput::CAFloating &) {
+ /* Nothing to check */
+ },
+ [&](const DerivationOutput::Deferred &) {
+ /* Nothing to check */
+ },
+ [&](const DerivationOutput::Impure &) {
+ /* Nothing to check */
+ },
+ }, i.second.raw());
+ }
+}
+
+
const Hash impureOutputHash = hashString(htSHA256, "impure");
nlohmann::json DerivationOutput::toJSON(