diff options
-rw-r--r-- | src/libexpr/eval.cc | 7 | ||||
-rw-r--r-- | src/libexpr/nixexpr.cc | 2 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 35 | ||||
-rw-r--r-- | tests/gc-runtime.nix.in | 2 |
4 files changed, 41 insertions, 5 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); } diff --git a/tests/gc-runtime.nix.in b/tests/gc-runtime.nix.in index 4ffe0435aa4d..5767d0370f75 100644 --- a/tests/gc-runtime.nix.in +++ b/tests/gc-runtime.nix.in @@ -1,7 +1,7 @@ let { # Test inline source file definitions. - builder = builtins.toFile " + builder = builtins.toFile "builder.sh" " mkdir $out cat > $out/program <<EOF |