about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc7
-rw-r--r--src/libexpr/nixexpr.cc2
-rw-r--r--src/libexpr/primops.cc35
3 files changed, 40 insertions, 4 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 416d43b33b7e..fa843b5d3b15 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -2,6 +2,7 @@
 #include "parser.hh"
 #include "hash.hh"
 #include "util.hh"
+#include "store.hh"
 #include "nixexpr-ast.hh"
 
 
@@ -256,7 +257,11 @@ string coerceToStringWithContext(EvalState & state,
     
     if (matchPath(e, s)) {
         isPath = true;
-        return aterm2String(s);
+        Path path = aterm2String(s);
+        if (isInStore(path)) {
+            context = ATinsert(context, makePath(toATerm(toStorePath(path))));
+        }
+        return path;
     }
 
     if (matchAttrs(e, es)) {
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 9622a03285f3..582eecaf75b3 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -297,6 +297,7 @@ string showType(Expr e)
 {
     ATerm t1, t2, t3;
     ATermList l1;
+    ATermBlob b1;
     int i1;
     if (matchStr(e, t1)) return "a string";
     if (matchPath(e, t1)) return "a path";
@@ -308,6 +309,7 @@ string showType(Expr e)
     if (matchFunction1(e, t1, t2, t3)) return "a function";
     if (matchAttrs(e, l1)) return "an attribute set";
     if (matchList(e, l1)) return "a list";
+    if (matchPrimOp(e, i1, b1, l1)) return "a partially applied built-in function";
     if (matchContext(e, l1, t1)) return "a context containing " + showType(t1);
     return "an unknown type";
 }
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 9a856ca40d21..926ea7b80927 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -512,12 +512,41 @@ static Expr primToXML(EvalState & state, const ATermVector & args)
 }
 
 
+static Expr unwrapContext(EvalState & state, Expr e, ATermList & context)
+{
+    context = ATempty;
+    e = evalExpr(state, e);
+    if (matchContext(e, context, e))
+        e = evalExpr(state, e);
+    return e;
+}
+
+
 /* Store a string in the Nix store as a source file that can be used
    as an input by derivations. */
 static Expr primToFile(EvalState & state, const ATermVector & args)
 {
-    string s = evalString(state, args[0]);
-    Path storePath = addTextToStore("", s, PathSet());
+    ATermList context;
+    string name = evalString(state, args[0]);
+    string contents = evalString(state,
+        unwrapContext(state, args[1], context));
+
+    PathSet refs;
+
+    for (ATermIterator i(context); i; ++i) {
+        ATerm s;
+        if (matchPath(*i, s)) {
+            assert(isStorePath(aterm2String(s)));
+            refs.insert(aterm2String(s));
+        }
+        else throw EvalError("in `toFile': the file cannot contain references to derivation outputs");
+    }
+    
+    Path storePath = addTextToStore(name, contents, refs);
+
+    /* Note: we don't need to wrap the result in a context, since
+       `storePath' itself has references to the paths used in
+       args[1]. */
     return makePath(toATerm(storePath));
 }
 
@@ -842,7 +871,6 @@ void EvalState::addPrimOps()
     addPrimOp("toString", 1, primToString);
     addPrimOp("__toPath", 1, primToPath);
     addPrimOp("__toXML", 1, primToXML);
-    addPrimOp("__toFile", 1, primToFile);
     addPrimOp("isNull", 1, primIsNull);
     addPrimOp("__isList", 1, primIsList);
     addPrimOp("dependencyClosure", 1, primDependencyClosure);
@@ -858,6 +886,7 @@ void EvalState::addPrimOps()
     addPrimOp("relativise", 2, primRelativise);
     addPrimOp("__add", 2, primAdd);
     addPrimOp("__lessThan", 2, primLessThan);
+    addPrimOp("__toFile", 2, primToFile);
 }