aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-11-27 15:01:32 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-11-27 15:01:32 +0100
commit6c98e6a5dec2bcbc25ddeb2c279aa4a0b274bd6a (patch)
tree2ef5df17cd5fc359c27f96adb3279deb791591a9 /src/libexpr
parent8b8ee53bc73769bb25d967ba259dabc9b23e2e6f (diff)
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.
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc1
-rw-r--r--src/libexpr/eval.hh2
-rw-r--r--src/libexpr/primops.cc32
3 files changed, 24 insertions, 11 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 31aaad548..9eb5fc758 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 432a0bad1..1d3baaab8 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 6876b2853..db27b716b 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);