diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 31aaad5485..9eb5fc7589 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -139,6 +139,7 @@ EvalState::EvalState() , sSystem(symbols.create("system")) , sOverrides(symbols.create("__overrides")) , sOutputName(symbols.create("outputName")) + , sIgnoreNulls(symbols.create("__ignoreNulls")) , baseEnv(allocEnv(128)) , baseEnvDispl(0) , staticBaseEnv(false, 0) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 432a0bad1c..1d3baaab8f 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -93,7 +93,7 @@ public: SymbolTable symbols; const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, - sSystem, sOverrides, sOutputName; + sSystem, sOverrides, sOutputName, sIgnoreNulls; /* If set, force copying files to the Nix store even if they already exist there. */ diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 6876b2853a..db27b716b0 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -310,16 +310,22 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) throw EvalError("required attribute `name' missing"); string drvName; Pos & posDrvName(*attr->pos); - try { + try { drvName = state.forceStringNoCtx(*attr->value); } catch (Error & e) { e.addPrefix(format("while evaluating the derivation attribute `name' at %1%:\n") % posDrvName); throw; } - + + /* Check whether null attributes should be ignored. */ + bool ignoreNulls = false; + attr = args[0]->attrs->find(state.sIgnoreNulls); + if (attr != args[0]->attrs->end()) + ignoreNulls = state.forceBool(*attr->value); + /* Build the derivation expression by processing the attributes. */ Derivation drv; - + PathSet context; string outputHash, outputHashAlgo; @@ -329,11 +335,17 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) outputs.insert("out"); foreach (Bindings::iterator, i, *args[0]->attrs) { + if (i->name == state.sIgnoreNulls) continue; string key = i->name; startNest(nest, lvlVomit, format("processing attribute `%1%'") % key); try { + if (ignoreNulls) { + state.forceValue(*i->value); + if (i->value->type == tNull) continue; + } + /* The `args' attribute is special: it supplies the command-line arguments to the builder. */ if (key == "args") { @@ -358,7 +370,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) else if (key == "outputHash") outputHash = s; else if (key == "outputHashAlgo") outputHashAlgo = s; else if (key == "outputHashMode") { - if (s == "recursive") outputHashRecursive = true; + if (s == "recursive") outputHashRecursive = true; else if (s == "flat") outputHashRecursive = false; else throw EvalError(format("invalid value `%1%' for `outputHashMode' attribute") % s); } @@ -390,13 +402,13 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) throw; } } - + /* Everything in the context of the strings in the derivation attributes should be added as dependencies of the resulting derivation. */ foreach (PathSet::iterator, i, context) { Path path = *i; - + /* Paths marked with `=' denote that the path of a derivation is explicitly passed to the builder. Since that allows the builder to gain access to every path in the dependency @@ -433,7 +445,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) else drv.inputSrcs.insert(path); } - + /* Do we have all required attributes? */ if (drv.builder == "") throw EvalError("required attribute `builder' missing"); @@ -450,14 +462,14 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* Handle fixed-output derivations. */ if (outputs.size() != 1 || *(outputs.begin()) != "out") throw Error("multiple outputs are not supported in fixed-output derivations"); - + HashType ht = parseHashType(outputHashAlgo); if (ht == htUnknown) throw EvalError(format("unknown hash algorithm `%1%'") % outputHashAlgo); Hash h = parseHash16or32(ht, outputHash); outputHash = printHash(h); if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo; - + Path outPath = makeFixedOutputPath(outputHashRecursive, ht, h, drvName); drv.env["out"] = outPath; drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash); @@ -477,7 +489,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* Use the masked derivation expression to compute the output path. */ Hash h = hashDerivationModulo(*store, drv); - + foreach (DerivationOutputs::iterator, i, drv.outputs) if (i->second.path == "") { Path outPath = makeOutputPath(i->first, h, drvName);