nix-shell/nix-build: Support .drv files again
Fixes #1663. Also handle '!<output-name>' (#1694).
This commit is contained in:
		
							parent
							
								
									0fc3e581e0
								
							
						
					
					
						commit
						90948a4e3a
					
				
					 6 changed files with 61 additions and 4 deletions
				
			
		|  | @ -1,6 +1,7 @@ | ||||||
| #include "get-drvs.hh" | #include "get-drvs.hh" | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
| #include "eval-inline.hh" | #include "eval-inline.hh" | ||||||
|  | #include "derivations.hh" | ||||||
| 
 | 
 | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <regex> | #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 | string DrvInfo::queryName() const | ||||||
| { | { | ||||||
|     if (name == "" && attrs) { |     if (name == "" && attrs) { | ||||||
|  |  | ||||||
|  | @ -37,6 +37,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     DrvInfo(EvalState & state) : state(&state) { }; |     DrvInfo(EvalState & state) : state(&state) { }; | ||||||
|     DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs); |     DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs); | ||||||
|  |     DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs); | ||||||
| 
 | 
 | ||||||
|     string queryName() const; |     string queryName() const; | ||||||
|     string querySystem() const; |     string querySystem() const; | ||||||
|  |  | ||||||
|  | @ -263,6 +263,8 @@ void mainWrapped(int argc, char * * argv) | ||||||
|     if (runEnv) |     if (runEnv) | ||||||
|         setenv("IN_NIX_SHELL", pure ? "pure" : "impure", 1); |         setenv("IN_NIX_SHELL", pure ? "pure" : "impure", 1); | ||||||
| 
 | 
 | ||||||
|  |     DrvInfos drvs; | ||||||
|  | 
 | ||||||
|     /* Parse the expressions. */ |     /* Parse the expressions. */ | ||||||
|     std::vector<Expr *> exprs; |     std::vector<Expr *> exprs; | ||||||
| 
 | 
 | ||||||
|  | @ -272,6 +274,8 @@ void mainWrapped(int argc, char * * argv) | ||||||
|         for (auto i : left) { |         for (auto i : left) { | ||||||
|             if (fromArgs) |             if (fromArgs) | ||||||
|                 exprs.push_back(state.parseExprFromString(i, absPath("."))); |                 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 |             else | ||||||
|                 /* If we're in a #! script, interpret filenames
 |                 /* If we're in a #! script, interpret filenames
 | ||||||
|                    relative to the script. */ |                    relative to the script. */ | ||||||
|  | @ -280,8 +284,6 @@ void mainWrapped(int argc, char * * argv) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     /* Evaluate them into derivations. */ |     /* Evaluate them into derivations. */ | ||||||
|     DrvInfos drvs; |  | ||||||
| 
 |  | ||||||
|     if (attrPaths.empty()) attrPaths = {""}; |     if (attrPaths.empty()) attrPaths = {""}; | ||||||
| 
 | 
 | ||||||
|     for (auto e : exprs) { |     for (auto e : exprs) { | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ source common.sh | ||||||
| 
 | 
 | ||||||
| clearStore | clearStore | ||||||
| 
 | 
 | ||||||
|  | rm -f $TEST_ROOT/result* | ||||||
|  | 
 | ||||||
| # Test whether read-only evaluation works when referring to the | # Test whether read-only evaluation works when referring to the | ||||||
| # ‘drvPath’ attribute. | # ‘drvPath’ attribute. | ||||||
| echo "evaluating c..." | echo "evaluating c..." | ||||||
|  | @ -28,7 +30,7 @@ echo "output path is $outPath" | ||||||
| [ "$(cat "$outPath"/file)" = "success" ] | [ "$(cat "$outPath"/file)" = "success" ] | ||||||
| 
 | 
 | ||||||
| # Test nix-build on a derivation with multiple outputs. | # 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-first ] | ||||||
| (! [ -e $TEST_ROOT/result-second ]) | (! [ -e $TEST_ROOT/result-second ]) | ||||||
| nix-build multiple-outputs.nix -A a.all -o $TEST_ROOT/result | 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" ] | [ "$(cat $TEST_ROOT/result-second/link/file)" = "first" ] | ||||||
| hash1=$(nix-store -q --hash $TEST_ROOT/result-second) | 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 | # Delete one of the outputs and rebuild it.  This will cause a hash | ||||||
| # rewrite. | # rewrite. | ||||||
| nix-store --delete $TEST_ROOT/result-second --ignore-liveness | nix-store --delete $TEST_ROOT/result-second --ignore-liveness | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ source common.sh | ||||||
| 
 | 
 | ||||||
| clearStore | 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 | test "$(cat $TEST_ROOT/result/foobar)" = FOOBAR | ||||||
| 
 | 
 | ||||||
| # The result should be retained by a GC. | # The result should be retained by a GC. | ||||||
|  | @ -17,3 +17,9 @@ test -e $target/foobar | ||||||
| rm $TEST_ROOT/result | rm $TEST_ROOT/result | ||||||
| nix-store --gc | nix-store --gc | ||||||
| if test -e $target/foobar; then false; fi | 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 ]] | ||||||
|  |  | ||||||
|  | @ -10,6 +10,13 @@ output=$(nix-shell --pure shell.nix -A shellDrv --run \ | ||||||
| 
 | 
 | ||||||
| [ "$output" = " - foo - bar" ] | [ "$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 | # Test nix-shell -p | ||||||
| output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') | output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') | ||||||
| [ "$output" = "foo bar" ] | [ "$output" = "foo bar" ] | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue