about summary refs log tree commit diff
path: root/src/libexpr/primops.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/primops.cc')
-rw-r--r--src/libexpr/primops.cc52
1 files changed, 41 insertions, 11 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 0e81f7b72fae..d5e1ce7be918 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -455,8 +455,8 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
     drvHashes[drvPath] = hashDerivationModulo(*store, drv);
 
     state.mkAttrs(v, 1 + drv.outputs.size());
-    mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));
     foreach (DerivationOutputs::iterator, i, drv.outputs) {
+        mkString(*state.allocAttr(v, state.symbols.create(i->first + "DrvPath")), drvPath, singleton<PathSet>("=" + i->first + "=" + drvPath));
         /* The output path of an output X is ‘<X>Path’,
            e.g. ‘outPath’. */
         mkString(*state.allocAttr(v, state.symbols.create(i->first + "Path")),
@@ -974,7 +974,14 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, Value * * args
     PathSet context2;
     foreach (PathSet::iterator, i, context) {
         Path p = *i;
-        if (p.at(0) == '=') p = "~" + string(p, 1);
+        if (p.at(0) == '=')
+        {
+            size_t index;
+            p = "~" + string(p, 1);
+            index = p.find("=");
+            if (index < p.find("/"))
+                p = "~" + string(p, index + 1);
+        }
         context2.insert(p);
     }
     
@@ -1052,15 +1059,6 @@ void EvalState::createBaseEnv()
     addPrimOp("__getEnv", 1, prim_getEnv);
     addPrimOp("__trace", 2, prim_trace);
 
-    // Derivations
-    addPrimOp("derivationStrict", 1, prim_derivationStrict);
-
-    /* Add a wrapper around the derivation primop that computes the
-       `drvPath' and `outPath' attributes lazily. */
-    string s = "attrs: let res = derivationStrict attrs; in attrs // { drvPath = res.drvPath; outPath = res.outPath; type = \"derivation\"; }";
-    mkThunk_(v, parseExprFromString(s, "/"));
-    addConstant("derivation", v);
-
     // Paths
     addPrimOp("__toPath", 1, prim_toPath);
     addPrimOp("__storePath", 1, prim_storePath);
@@ -1109,6 +1107,38 @@ void EvalState::createBaseEnv()
     addPrimOp("__parseDrvName", 1, prim_parseDrvName);
     addPrimOp("__compareVersions", 2, prim_compareVersions);
 
+    // Derivations
+    addPrimOp("derivationStrict", 1, prim_derivationStrict);
+
+    /* Add a wrapper around the derivation primop that computes the
+       `drvPath' and `outPath' attributes lazily. */
+    string s = "attrs: \
+      let \
+        strict = derivationStrict attrs; \
+        attrValues = attrs: \
+          map (name: builtins.getAttr name attrs) (builtins.attrNames attrs); \
+        outputToAttrListElement = output: \
+          let \
+            outPath = builtins.getAttr (output + \"Path\") strict; \
+            drvPath = builtins.getAttr (output + \"DrvPath\") strict; \
+          in { \
+            name = output; \
+            value = attrs // { \
+              inherit outPath drvPath; \
+              type = \"derivation\"; \
+              currentOutput = output; \
+            } // outputsAttrs // { all = allList; }; \
+          }; \
+        outputsList = if attrs ? outputs then \
+          map outputToAttrListElement attrs.outputs else \
+          [ (outputToAttrListElement \"out\") ]; \
+        outputsAttrs = builtins.listToAttrs outputsList; \
+        allList = attrValues outputsAttrs; \
+        head = if attrs ? outputs then builtins.head attrs.outputs else \"out\"; \
+      in builtins.getAttr head outputsAttrs";
+    mkThunk_(v, parseExprFromString(s, "/"));
+    addConstant("derivation", v);
+
     /* Now that we've added all primops, sort the `builtins' attribute
        set, because attribute lookups expect it to be sorted. */
     baseEnv.values[0]->attrs->sort();