about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/get-drvs.cc28
-rw-r--r--src/libexpr/get-drvs.hh1
-rwxr-xr-xsrc/nix-build/nix-build.cc6
-rw-r--r--tests/multiple-outputs.sh15
-rw-r--r--tests/nix-build.sh8
-rw-r--r--tests/nix-shell.sh7
6 files changed, 61 insertions, 4 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index d5bc42352a26..d38ed2df3b18 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -1,6 +1,7 @@
 #include "get-drvs.hh"
 #include "util.hh"
 #include "eval-inline.hh"
+#include "derivations.hh"
 
 #include <cstring>
 #include <regex>
@@ -15,6 +16,33 @@ DrvInfo::DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs)
 }
 
 
+DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs)
+    : state(&state), attrs(nullptr), attrPath("")
+{
+    auto spec = parseDrvPathWithOutputs(drvPathWithOutputs);
+
+    drvPath = spec.first;
+
+    auto drv = store->derivationFromPath(drvPath);
+
+    name = storePathToName(drvPath);
+
+    if (spec.second.size() > 1)
+        throw Error("building more than one derivation output is not supported, in '%s'", drvPathWithOutputs);
+
+    outputName =
+        spec.second.empty()
+        ? get(drv.env, "outputName", "out")
+        : *spec.second.begin();
+
+    auto i = drv.outputs.find(outputName);
+    if (i == drv.outputs.end())
+        throw Error("derivation '%s' does not have output '%s'", drvPath, outputName);
+
+    outPath = i->second.path;
+}
+
+
 string DrvInfo::queryName() const
 {
     if (name == "" && attrs) {
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index 32294e458751..4d9128e3f448 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -37,6 +37,7 @@ public:
 
     DrvInfo(EvalState & state) : state(&state) { };
     DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs);
+    DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs);
 
     string queryName() const;
     string querySystem() const;
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index 21b0a18dd887..58366daa6e86 100755
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -263,6 +263,8 @@ void mainWrapped(int argc, char * * argv)
     if (runEnv)
         setenv("IN_NIX_SHELL", pure ? "pure" : "impure", 1);
 
+    DrvInfos drvs;
+
     /* Parse the expressions. */
     std::vector<Expr *> exprs;
 
@@ -272,6 +274,8 @@ void mainWrapped(int argc, char * * argv)
         for (auto i : left) {
             if (fromArgs)
                 exprs.push_back(state.parseExprFromString(i, absPath(".")));
+            else if (store->isStorePath(i) && std::regex_match(i, std::regex(".*\\.drv(!.*)?")))
+                drvs.push_back(DrvInfo(state, store, i));
             else
                 /* If we're in a #! script, interpret filenames
                    relative to the script. */
@@ -280,8 +284,6 @@ void mainWrapped(int argc, char * * argv)
         }
 
     /* Evaluate them into derivations. */
-    DrvInfos drvs;
-
     if (attrPaths.empty()) attrPaths = {""};
 
     for (auto e : exprs) {
diff --git a/tests/multiple-outputs.sh b/tests/multiple-outputs.sh
index ced6d758f4af..bedbc39a4ebf 100644
--- a/tests/multiple-outputs.sh
+++ b/tests/multiple-outputs.sh
@@ -2,6 +2,8 @@ source common.sh
 
 clearStore
 
+rm -f $TEST_ROOT/result*
+
 # Test whether read-only evaluation works when referring to the
 # ‘drvPath’ attribute.
 echo "evaluating c..."
@@ -28,7 +30,7 @@ echo "output path is $outPath"
 [ "$(cat "$outPath"/file)" = "success" ]
 
 # Test nix-build on a derivation with multiple outputs.
-nix-build multiple-outputs.nix -A a -o $TEST_ROOT/result
+outPath1=$(nix-build multiple-outputs.nix -A a -o $TEST_ROOT/result)
 [ -e $TEST_ROOT/result-first ]
 (! [ -e $TEST_ROOT/result-second ])
 nix-build multiple-outputs.nix -A a.all -o $TEST_ROOT/result
@@ -37,6 +39,17 @@ nix-build multiple-outputs.nix -A a.all -o $TEST_ROOT/result
 [ "$(cat $TEST_ROOT/result-second/link/file)" = "first" ]
 hash1=$(nix-store -q --hash $TEST_ROOT/result-second)
 
+outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a) --no-out-link)
+[[ $outPath1 = $outPath2 ]]
+
+outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a.first) --no-out-link)
+[[ $outPath1 = $outPath2 ]]
+
+outPath2=$(nix-build $(nix-instantiate multiple-outputs.nix -A a.second) --no-out-link)
+[[ $(cat $outPath2/file) = second ]]
+
+[[ $(nix-build $(nix-instantiate multiple-outputs.nix -A a.all) --no-out-link | wc -l) -eq 2 ]]
+
 # Delete one of the outputs and rebuild it.  This will cause a hash
 # rewrite.
 nix-store --delete $TEST_ROOT/result-second --ignore-liveness
diff --git a/tests/nix-build.sh b/tests/nix-build.sh
index dc0e99c73621..395264863196 100644
--- a/tests/nix-build.sh
+++ b/tests/nix-build.sh
@@ -2,7 +2,7 @@ source common.sh
 
 clearStore
 
-nix-build dependencies.nix -o $TEST_ROOT/result
+outPath=$(nix-build dependencies.nix -o $TEST_ROOT/result)
 test "$(cat $TEST_ROOT/result/foobar)" = FOOBAR
 
 # The result should be retained by a GC.
@@ -17,3 +17,9 @@ test -e $target/foobar
 rm $TEST_ROOT/result
 nix-store --gc
 if test -e $target/foobar; then false; fi
+
+outPath2=$(nix-build $(nix-instantiate dependencies.nix) --no-out-link)
+[[ $outPath = $outPath2 ]]
+
+outPath2=$(nix-build $(nix-instantiate dependencies.nix)!out --no-out-link)
+[[ $outPath = $outPath2 ]]
diff --git a/tests/nix-shell.sh b/tests/nix-shell.sh
index f0f34a5f8705..f7cac6ecf8ef 100644
--- a/tests/nix-shell.sh
+++ b/tests/nix-shell.sh
@@ -10,6 +10,13 @@ output=$(nix-shell --pure shell.nix -A shellDrv --run \
 
 [ "$output" = " - foo - bar" ]
 
+# Test nix-shell on a .drv
+[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \
+    'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]]
+
+[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \
+    'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]]
+
 # Test nix-shell -p
 output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"')
 [ "$output" = "foo bar" ]