Optionally ignore null-valued derivation attributes
This allows adding attributes like attr = if stdenv.system == "bla" then something else null; without changing the resulting derivation on non-<bla> platforms. We once considered adding a special "ignore" value for this purpose, but using null seems more elegant.
This commit is contained in:
parent
8b8ee53bc7
commit
6c98e6a5de
3 changed files with 24 additions and 11 deletions
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue