about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore27
-rw-r--r--src/libexpr/eval.cc1
-rw-r--r--src/libexpr/eval.hh2
-rw-r--r--src/libexpr/primops.cc52
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/multiple-outputs.a.builder.sh6
-rw-r--r--tests/multiple-outputs.b.builder.sh7
-rw-r--r--tests/multiple-outputs.nix23
-rw-r--r--tests/multiple-outputs.sh15
9 files changed, 107 insertions, 30 deletions
diff --git a/.gitignore b/.gitignore
index d4e8d17de8cf..5e1561829379 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,23 +61,11 @@
 # /externals/
 /externals/Makefile
 /externals/Makefile.in
-/externals/aterm-*
-/externals/have-aterm
-/externals/build-aterm
-/externals/inst-aterm
 /externals/bzip2-*
-/externals/have-bzip2
 /externals/build-bzip2
 /externals/inst-bzip2
-
-# /make/examples/aterm/
-/make/examples/aterm/result*
-
-# /make/examples/aterm/aterm/
-/make/examples/aterm/aterm/*
-
-# /make/examples/aterm/test/
-/make/examples/aterm/test/*
+/externals/sqlite-*
+/externals/build-sqlite
 
 # /misc/
 /misc/Makefile.in
@@ -100,13 +88,16 @@
 /scripts/nix-channel
 /scripts/nix-build
 /scripts/nix-copy-closure
-/scripts/readmanifest.pm
-/scripts/readconfig.pm
+/scripts/nix-generate-patches
+/scripts/NixConfig.pm
+/scripts/NixManifest.pm
+/scripts/GeneratePatches.pm
 /scripts/download-using-manifests.pl
 /scripts/copy-from-other-stores.pl
-/scripts/generate-patches.pl
 /scripts/find-runtime-roots.pl
 /scripts/build-remote.pl
+/scripts/nix-reduce-build
+/scripts/nix-http-export.cgi
 
 # /src/
 /src/Makefile
@@ -168,6 +159,7 @@
 /src/libstore/derivations-ast.cc
 /src/libstore/derivations-ast.hh
 /src/libstore/.libs
+/src/libstore/schema.sql.hh
 
 # /src/libutil/
 /src/libutil/Makefile
@@ -242,6 +234,7 @@
 /tests/config.nix
 /tests/common.sh
 /tests/dummy
+/tests/result*
 
 # /tests/lang/
 /tests/lang/*.out
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 2b97b76fb776..64e6cbe6419b 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -133,6 +133,7 @@ string showType(const Value & v)
 EvalState::EvalState()
     : sWith(symbols.create("<with>"))
     , sOutPath(symbols.create("outPath"))
+    , sCurrentOutput(symbols.create("currentOutput"))
     , sDrvPath(symbols.create("drvPath"))
     , sType(symbols.create("type"))
     , sMeta(symbols.create("meta"))
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 694d4407b847..3816f36bd6a7 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -204,7 +204,7 @@ public:
     SymbolTable symbols;
 
     const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName,
-        sSystem, sOverrides;
+        sSystem, sOverrides, sCurrentOutput;
 
 private:
     SrcToStore srcToStore; 
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();
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 676a9c387b18..0418f73e6cf5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,7 +8,7 @@ TESTS = init.sh hash.sh lang.sh add.sh simple.sh dependencies.sh \
   referrers.sh user-envs.sh logging.sh nix-build.sh misc.sh fixed.sh \
   gc-runtime.sh install-package.sh check-refs.sh filter-source.sh \
   remote-store.sh export.sh export-graph.sh negative-caching.sh \
-  binary-patching.sh timeout.sh secure-drv-outputs.sh
+  binary-patching.sh timeout.sh secure-drv-outputs.sh multiple-outputs.sh
 
 XFAIL_TESTS =
 
@@ -35,6 +35,8 @@ EXTRA_DIST = $(TESTS) \
   binary-patching.nix \
   timeout.nix timeout.builder.sh \
   secure-drv-outputs.nix \
+  multiple-outputs.nix \
+  multiple-outputs.a.builder.sh multiple-outputs.b.builder.sh \
   $(wildcard lang/*.nix) $(wildcard lang/*.exp) $(wildcard lang/*.exp.xml) $(wildcard lang/*.flags) $(wildcard lang/dir*/*.nix) \
   common.sh.in
 
diff --git a/tests/multiple-outputs.a.builder.sh b/tests/multiple-outputs.a.builder.sh
new file mode 100644
index 000000000000..657b7ea0adc5
--- /dev/null
+++ b/tests/multiple-outputs.a.builder.sh
@@ -0,0 +1,6 @@
+mkdir $first
+mkdir $second
+test -z $all
+
+echo "second" > $first/file
+echo "first" > $second/file
diff --git a/tests/multiple-outputs.b.builder.sh b/tests/multiple-outputs.b.builder.sh
new file mode 100644
index 000000000000..bc63fc0681b0
--- /dev/null
+++ b/tests/multiple-outputs.b.builder.sh
@@ -0,0 +1,7 @@
+mkdir $out
+test "$firstOutput $secondOutput" = "$allOutputs"
+test "$defaultOutput" = "$firstOutput"
+test "$(cat $first/file)" = "second"
+test "$(cat $second/file)" = "first"
+
+echo "success" > $out/file
diff --git a/tests/multiple-outputs.nix b/tests/multiple-outputs.nix
new file mode 100644
index 000000000000..e8fbf91bfa89
--- /dev/null
+++ b/tests/multiple-outputs.nix
@@ -0,0 +1,23 @@
+with import ./config.nix;
+
+let
+
+  a = mkDerivation {
+    name = "multiple-outputs-a";
+    outputs = [ "first" "second" ];
+    builder = ./multiple-outputs.a.builder.sh;
+    helloString = "Hello, world!";
+  };
+
+in
+
+assert a.second.helloString == "Hello, world!";
+
+mkDerivation {
+  defaultOutput = a;
+  firstOutput = a.first.first;
+  secondOutput = a.second.first.first.second.second.first.second;
+  allOutputs = a.all;
+  name = "multiple-outputs-b";
+  builder = ./multiple-outputs.b.builder.sh;
+}
diff --git a/tests/multiple-outputs.sh b/tests/multiple-outputs.sh
new file mode 100644
index 000000000000..f4cd01234c5b
--- /dev/null
+++ b/tests/multiple-outputs.sh
@@ -0,0 +1,15 @@
+source common.sh
+
+echo "Testing multiple outputs..."
+
+drvPath=$($nixinstantiate multiple-outputs.nix)
+
+echo "derivation is $drvPath"
+
+outPath=$($nixstore -rvv "$drvPath")
+
+echo "output path is $outPath"
+
+text=$(cat "$outPath"/file)
+if test "$text" != "success"; then exit 1; fi
+