about summary refs log tree commit diff
path: root/src/libexpr/primops.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-11-27T14·01+0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-11-27T14·01+0100
commit6c98e6a5dec2bcbc25ddeb2c279aa4a0b274bd6a (patch)
tree2ef5df17cd5fc359c27f96adb3279deb791591a9 /src/libexpr/primops.cc
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/primops.cc')
-rw-r--r--src/libexpr/primops.cc32
1 files changed, 22 insertions, 10 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 6876b2853add..db27b716b023 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);