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