nix-build/nix-shell: Eliminate call to nix-instantiate / nix-store
Note that this removes the need for a derivation symlink, so the --drv-path and --add-drv-link flags now do nothing.
This commit is contained in:
		
							parent
							
								
									c94f3d5575
								
							
						
					
					
						commit
						4c9ff89c26
					
				
					 6 changed files with 449 additions and 511 deletions
				
			
		|  | @ -118,6 +118,8 @@ public: | ||||||
|     Expr * parseExprFromString(const string & s, const Path & basePath, StaticEnv & staticEnv); |     Expr * parseExprFromString(const string & s, const Path & basePath, StaticEnv & staticEnv); | ||||||
|     Expr * parseExprFromString(const string & s, const Path & basePath); |     Expr * parseExprFromString(const string & s, const Path & basePath); | ||||||
| 
 | 
 | ||||||
|  |     Expr * parseStdin(); | ||||||
|  | 
 | ||||||
|     /* Evaluate an expression read from the given file to normal
 |     /* Evaluate an expression read from the given file to normal
 | ||||||
|        form. */ |        form. */ | ||||||
|     void evalFile(const Path & path, Value & v); |     void evalFile(const Path & path, Value & v); | ||||||
|  |  | ||||||
|  | @ -601,6 +601,13 @@ Expr * EvalState::parseExprFromString(const string & s, const Path & basePath) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | Expr * EvalState::parseStdin() | ||||||
|  | { | ||||||
|  |     //Activity act(*logger, lvlTalkative, format("parsing standard input")); | ||||||
|  |     return parseExprFromString(drainFD(0), absPath(".")); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void EvalState::addToSearchPath(const string & s) | void EvalState::addToSearchPath(const string & s) | ||||||
| { | { | ||||||
|     size_t pos = s.find('='); |     size_t pos = s.find('='); | ||||||
|  |  | ||||||
|  | @ -222,7 +222,14 @@ struct LegacyArgs : public MixCommonArgs | ||||||
| void parseCmdLine(int argc, char * * argv, | void parseCmdLine(int argc, char * * argv, | ||||||
|     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg) |     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg) | ||||||
| { | { | ||||||
|     LegacyArgs(baseNameOf(argv[0]), parseArg).parseCmdline(argvToStrings(argc, argv)); |     parseCmdLine(baseNameOf(argv[0]), argvToStrings(argc, argv), parseArg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void parseCmdLine(const string & programName, const Strings & args, | ||||||
|  |     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg) | ||||||
|  | { | ||||||
|  |     LegacyArgs(programName, parseArg).parseCmdline(args); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,6 +25,9 @@ void initNix(); | ||||||
| void parseCmdLine(int argc, char * * argv, | void parseCmdLine(int argc, char * * argv, | ||||||
|     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg); |     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg); | ||||||
| 
 | 
 | ||||||
|  | void parseCmdLine(const string & programName, const Strings & args, | ||||||
|  |     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg); | ||||||
|  | 
 | ||||||
| void printVersion(const string & programName); | void printVersion(const string & programName); | ||||||
| 
 | 
 | ||||||
| /* Ugh.  No better place to put this. */ | /* Ugh.  No better place to put this. */ | ||||||
|  |  | ||||||
|  | @ -5,8 +5,6 @@ | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| #include <unistd.h> |  | ||||||
| 
 |  | ||||||
| #include "store-api.hh" | #include "store-api.hh" | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
| #include "derivations.hh" | #include "derivations.hh" | ||||||
|  | @ -14,7 +12,10 @@ | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
| #include "shared.hh" | #include "shared.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
|  | #include "eval-inline.hh" | ||||||
| #include "get-drvs.hh" | #include "get-drvs.hh" | ||||||
|  | #include "common-opts.hh" | ||||||
|  | #include "attr-path.hh" | ||||||
| 
 | 
 | ||||||
| using namespace nix; | using namespace nix; | ||||||
| using namespace std::string_literals; | using namespace std::string_literals; | ||||||
|  | @ -65,34 +66,26 @@ std::vector<string> shellwords(const string & s) | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void maybePrintExecError(ExecError & e) | void mainWrapped(int argc, char * * argv) | ||||||
| { | { | ||||||
|     if (WIFEXITED(e.status)) |  | ||||||
|         throw Exit(WEXITSTATUS(e.status)); |  | ||||||
|     else |  | ||||||
|         throw e; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char ** argv) |  | ||||||
| { |  | ||||||
|     return handleExceptions(argv[0], [&]() { |  | ||||||
|     initNix(); |     initNix(); | ||||||
|     initGC(); |     initGC(); | ||||||
| 
 | 
 | ||||||
|         auto store = openStore(); |  | ||||||
|     auto dryRun = false; |     auto dryRun = false; | ||||||
|         auto verbose = false; |  | ||||||
|     auto runEnv = std::regex_search(argv[0], std::regex("nix-shell$")); |     auto runEnv = std::regex_search(argv[0], std::regex("nix-shell$")); | ||||||
|     auto pure = false; |     auto pure = false; | ||||||
|     auto fromArgs = false; |     auto fromArgs = false; | ||||||
|     auto packages = false; |     auto packages = false; | ||||||
|     // Same condition as bash uses for interactive shells
 |     // Same condition as bash uses for interactive shells
 | ||||||
|     auto interactive = isatty(STDIN_FILENO) && isatty(STDERR_FILENO); |     auto interactive = isatty(STDIN_FILENO) && isatty(STDERR_FILENO); | ||||||
| 
 |     Strings attrPaths; | ||||||
|         Strings instArgs; |     Strings left; | ||||||
|         Strings buildArgs; |  | ||||||
|         Strings exprs; |  | ||||||
|     Strings searchPath; |     Strings searchPath; | ||||||
|  |     std::map<string, string> autoArgs_; | ||||||
|  |     RepairFlag repair = NoRepair; | ||||||
|  |     Path gcRoot; | ||||||
|  |     BuildMode buildMode = bmNormal; | ||||||
|  |     bool readStdin = false; | ||||||
| 
 | 
 | ||||||
|     auto shell = getEnv("SHELL", "/bin/sh"); |     auto shell = getEnv("SHELL", "/bin/sh"); | ||||||
|     std::string envCommand; // interactive shell
 |     std::string envCommand; // interactive shell
 | ||||||
|  | @ -107,9 +100,8 @@ int main(int argc, char ** argv) | ||||||
|     AutoDelete tmpDir(createTempDir("", myName)); |     AutoDelete tmpDir(createTempDir("", myName)); | ||||||
| 
 | 
 | ||||||
|     std::string outLink = "./result"; |     std::string outLink = "./result"; | ||||||
|         auto drvLink = (Path) tmpDir + "/derivation"; |  | ||||||
| 
 | 
 | ||||||
|         std::vector<string> args; |     Strings args; | ||||||
|     for (int i = 1; i < argc; ++i) |     for (int i = 1; i < argc; ++i) | ||||||
|         args.push_back(argv[i]); |         args.push_back(argv[i]); | ||||||
| 
 | 
 | ||||||
|  | @ -137,152 +129,74 @@ int main(int argc, char ** argv) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|         for (size_t n = 0; n < args.size(); ++n) { |     parseCmdLine(myName, args, [&](Strings::iterator & arg, const Strings::iterator & end) { | ||||||
|             auto arg = args[n]; |         if (*arg == "--help") { | ||||||
| 
 |  | ||||||
|             if (arg == "--help") { |  | ||||||
|             deletePath(tmpDir); |             deletePath(tmpDir); | ||||||
|             showManPage(myName); |             showManPage(myName); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--version") |         else if (*arg == "--version") | ||||||
|             printVersion(myName); |             printVersion(myName); | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--add-drv-link") { |         else if (*arg == "--add-drv-link") | ||||||
|                 drvLink = "./derivation"; |             ; // obsolete
 | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--no-out-link" || arg == "--no-link") { |         else if (*arg == "--no-out-link" || *arg == "--no-link") | ||||||
|             outLink = (Path) tmpDir + "/result"; |             outLink = (Path) tmpDir + "/result"; | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--drv-link") { |         else if (*arg == "--attr" || *arg == "-A") | ||||||
|                 n++; |             attrPaths.push_back(getArg(*arg, arg, end)); | ||||||
|                 if (n >= args.size()) { |  | ||||||
|                     throw UsageError("--drv-link requires an argument"); |  | ||||||
|                 } |  | ||||||
|                 drvLink = args[n]; |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--out-link" || arg == "-o") { |         else if (*arg == "--drv-link") | ||||||
|                 n++; |             getArg(*arg, arg, end); // obsolete
 | ||||||
|                 if (n >= args.size()) { |  | ||||||
|                     throw UsageError(format("%1% requires an argument") % arg); |  | ||||||
|                 } |  | ||||||
|                 outLink = args[n]; |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--attr" || arg == "-A" || arg == "-I") { |         else if (*arg == "--out-link" || *arg == "-o") | ||||||
|                 n++; |             outLink = getArg(*arg, arg, end); | ||||||
|                 if (n >= args.size()) { |  | ||||||
|                     throw UsageError(format("%1% requires an argument") % arg); |  | ||||||
|                 } |  | ||||||
|                 instArgs.push_back(arg); |  | ||||||
|                 instArgs.push_back(args[n]); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--arg" || arg == "--argstr") { |         else if (parseAutoArgs(arg, end, autoArgs_)) | ||||||
|                 if (n + 2 >= args.size()) { |             ; | ||||||
|                     throw UsageError(format("%1% requires two arguments") % arg); |  | ||||||
|                 } |  | ||||||
|                 instArgs.push_back(arg); |  | ||||||
|                 instArgs.push_back(args[n + 1]); |  | ||||||
|                 instArgs.push_back(args[n + 2]); |  | ||||||
|                 n += 2; |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--option") { |         else if (parseSearchPathArg(arg, end, searchPath)) | ||||||
|                 if (n + 2 >= args.size()) { |             ; | ||||||
|                     throw UsageError(format("%1% requires two arguments") % arg); |  | ||||||
|                 } |  | ||||||
|                 instArgs.push_back(arg); |  | ||||||
|                 instArgs.push_back(args[n + 1]); |  | ||||||
|                 instArgs.push_back(args[n + 2]); |  | ||||||
|                 buildArgs.push_back(arg); |  | ||||||
|                 buildArgs.push_back(args[n + 1]); |  | ||||||
|                 buildArgs.push_back(args[n + 2]); |  | ||||||
|                 settings.set(args[n + 1], args[n + 2]); |  | ||||||
|                 n += 2; |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--max-jobs" || arg == "-j" || arg == "--max-silent-time" || arg == "--cores" || arg == "--timeout" || arg == "--add-root") { |         else if (*arg == "--add-root") | ||||||
|                 n++; |             gcRoot = getArg(*arg, arg, end); | ||||||
|                 if (n >= args.size()) { |  | ||||||
|                     throw UsageError(format("%1% requires an argument") % arg); |  | ||||||
|                 } |  | ||||||
|                 buildArgs.push_back(arg); |  | ||||||
|                 buildArgs.push_back(args[n]); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--dry-run") { |         else if (*arg == "--dry-run") | ||||||
|                 buildArgs.push_back("--dry-run"); |  | ||||||
|             dryRun = true; |             dryRun = true; | ||||||
|  | 
 | ||||||
|  |         else if (*arg == "--repair") { | ||||||
|  |             repair = Repair; | ||||||
|  |             buildMode = bmRepair; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--show-trace") { |         else if (*arg == "--run-env") // obsolete
 | ||||||
|                 instArgs.push_back(arg); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             else if (arg == "-") { |  | ||||||
|                 exprs = Strings{"-"}; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             else if (arg == "--verbose" || (arg.size() >= 2 && arg.substr(0, 2) == "-v")) { |  | ||||||
|                 buildArgs.push_back(arg); |  | ||||||
|                 instArgs.push_back(arg); |  | ||||||
|                 verbose = true; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             else if (arg == "--quiet" || arg == "--repair") { |  | ||||||
|                 buildArgs.push_back(arg); |  | ||||||
|                 instArgs.push_back(arg); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             else if (arg == "--check") { |  | ||||||
|                 buildArgs.push_back(arg); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             else if (arg == "--run-env") { // obsolete
 |  | ||||||
|             runEnv = true; |             runEnv = true; | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--command" || arg == "--run") { |         else if (*arg == "--command" || *arg == "--run") { | ||||||
|                 n++; |             if (*arg == "--run") | ||||||
|                 if (n >= args.size()) { |  | ||||||
|                     throw UsageError(format("%1% requires an argument") % arg); |  | ||||||
|                 } |  | ||||||
|                 envCommand = args[n] + "\nexit"; |  | ||||||
|                 if (arg == "--run") |  | ||||||
|                 interactive = false; |                 interactive = false; | ||||||
|  |             envCommand = getArg(*arg, arg, end) + "\nexit"; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--exclude") { |         else if (*arg == "--check") | ||||||
|                 n++; |             buildMode = bmCheck; | ||||||
|                 if (n >= args.size()) { |  | ||||||
|                     throw UsageError(format("%1% requires an argument") % arg); |  | ||||||
|                 } |  | ||||||
|                 envExclude.push_back(args[n]); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--pure") { pure = true; } |         else if (*arg == "--exclude") | ||||||
|             else if (arg == "--impure") { pure = false; } |             envExclude.push_back(getArg(*arg, arg, end)); | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--expr" || arg == "-E") { |         else if (*arg == "--expr" || *arg == "-E") | ||||||
|             fromArgs = true; |             fromArgs = true; | ||||||
|                 instArgs.push_back("--expr"); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "--packages" || arg == "-p") { |         else if (*arg == "--pure") pure = true; | ||||||
|  |         else if (*arg == "--impure") pure = false; | ||||||
|  | 
 | ||||||
|  |         else if (*arg == "--packages" || *arg == "-p") | ||||||
|             packages = true; |             packages = true; | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (inShebang && arg == "-i") { |         else if (inShebang && *arg == "-i") { | ||||||
|                 n++; |             auto interpreter = getArg(*arg, arg, end); | ||||||
|                 if (n >= args.size()) { |  | ||||||
|                     throw UsageError(format("%1% requires an argument") % arg); |  | ||||||
|                 } |  | ||||||
|             interactive = false; |             interactive = false; | ||||||
|                 auto interpreter = args[n]; |  | ||||||
|             auto execArgs = ""; |             auto execArgs = ""; | ||||||
| 
 | 
 | ||||||
|             auto shellEscape = [](const string & s) { |             auto shellEscape = [](const string & s) { | ||||||
|  | @ -311,91 +225,137 @@ int main(int argc, char ** argv) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|             else if (!arg.empty() && arg[0] == '-') { |         else if (*arg == "-") | ||||||
|                 buildArgs.push_back(arg); |             readStdin = true; | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else if (arg == "-Q" || arg == "--no-build-output") { |         else if (*arg != "" && arg->at(0) == '-') | ||||||
|                 buildArgs.push_back(arg); |             return false; | ||||||
|                 instArgs.push_back(arg); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             else { |         else | ||||||
|                 exprs.push_back(arg); |             left.push_back(*arg); | ||||||
|             } | 
 | ||||||
|         } |         return true; | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     if (packages && fromArgs) | ||||||
|  |         throw UsageError("‘-p’ and ‘-E’ are mutually exclusive"); | ||||||
|  | 
 | ||||||
|  |     auto store = openStore(); | ||||||
| 
 | 
 | ||||||
|     EvalState state(searchPath, store); |     EvalState state(searchPath, store); | ||||||
|  |     state.repair = repair; | ||||||
| 
 | 
 | ||||||
|         if (packages && fromArgs) { |     Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); | ||||||
|             throw UsageError("‘-p’ and ‘-E’ are mutually exclusive"); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|     if (packages) { |     if (packages) { | ||||||
|             instArgs.push_back("--expr"); |  | ||||||
|         std::ostringstream joined; |         std::ostringstream joined; | ||||||
|         joined << "with import <nixpkgs> { }; (pkgs.runCommandCC or pkgs.runCommand) \"shell\" { buildInputs = [ "; |         joined << "with import <nixpkgs> { }; (pkgs.runCommandCC or pkgs.runCommand) \"shell\" { buildInputs = [ "; | ||||||
|             for (const auto & i : exprs) |         for (const auto & i : left) | ||||||
|             joined << '(' << i << ") "; |             joined << '(' << i << ") "; | ||||||
|         joined << "]; } \"\""; |         joined << "]; } \"\""; | ||||||
|             exprs = Strings{joined.str()}; |         fromArgs = true; | ||||||
|  |         left = {joined.str()}; | ||||||
|     } else if (!fromArgs) { |     } else if (!fromArgs) { | ||||||
|             if (exprs.empty() && runEnv && access("shell.nix", F_OK) == 0) |         if (left.empty() && runEnv && pathExists("shell.nix")) | ||||||
|                 exprs.push_back("shell.nix"); |             left = {"shell.nix"}; | ||||||
|             if (exprs.empty()) |         if (left.empty()) | ||||||
|                 exprs.push_back("default.nix"); |             left = {"default.nix"}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (runEnv) |     if (runEnv) | ||||||
|         setenv("IN_NIX_SHELL", pure ? "pure" : "impure", 1); |         setenv("IN_NIX_SHELL", pure ? "pure" : "impure", 1); | ||||||
| 
 | 
 | ||||||
|         for (auto & expr : exprs) { |     /* Parse the expressions. */ | ||||||
|             // Instantiate.
 |     std::vector<Expr *> exprs; | ||||||
|             std::vector<string> drvPaths; |  | ||||||
|             if (!std::regex_match(expr, std::regex("^/.*\\.drv$"))) { |  | ||||||
|                 // If we're in a #! script, interpret filenames relative to the
 |  | ||||||
|                 // script.
 |  | ||||||
|                 if (inShebang && !packages) |  | ||||||
|                     expr = absPath(expr, dirOf(script)); |  | ||||||
| 
 | 
 | ||||||
|                 Strings instantiateArgs{"--add-root", drvLink, "--indirect"}; |     if (readStdin) | ||||||
|                 for (const auto & arg : instArgs) |         exprs = {state.parseStdin()}; | ||||||
|                     instantiateArgs.push_back(arg); |     else | ||||||
|                 instantiateArgs.push_back(expr); |         for (auto i : left) { | ||||||
|                 try { |             if (fromArgs) | ||||||
|                     auto instOutput = runProgram(settings.nixBinDir + "/nix-instantiate", false, instantiateArgs); |                 exprs.push_back(state.parseExprFromString(i, absPath("."))); | ||||||
|                     drvPaths = tokenizeString<std::vector<string>>(instOutput); |             else | ||||||
|                 } catch (ExecError & e) { |                 /* If we're in a #! script, interpret filenames
 | ||||||
|                     maybePrintExecError(e); |                    relative to the script. */ | ||||||
|  |                 exprs.push_back(state.parseExprFromFile(resolveExprPath(lookupFileArg(state, | ||||||
|  |                     inShebang && !packages ? absPath(i, dirOf(script)) : i)))); | ||||||
|         } |         } | ||||||
|             } else { | 
 | ||||||
|                 drvPaths.push_back(expr); |     /* Evaluate them into derivations. */ | ||||||
|  |     DrvInfos drvs; | ||||||
|  | 
 | ||||||
|  |     if (attrPaths.empty()) attrPaths = {""}; | ||||||
|  | 
 | ||||||
|  |     for (auto e : exprs) { | ||||||
|  |         Value vRoot; | ||||||
|  |         state.eval(e, vRoot); | ||||||
|  | 
 | ||||||
|  |         for (auto & i : attrPaths) { | ||||||
|  |             Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot)); | ||||||
|  |             state.forceValue(v); | ||||||
|  |             getDerivations(state, v, "", autoArgs, drvs, false); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     auto buildPaths = [&](const PathSet & paths) { | ||||||
|  |         /* Note: we do this even when !printMissing to efficiently
 | ||||||
|  |            fetch binary cache data. */ | ||||||
|  |         unsigned long long downloadSize, narSize; | ||||||
|  |         PathSet willBuild, willSubstitute, unknown; | ||||||
|  |         store->queryMissing(paths, | ||||||
|  |             willBuild, willSubstitute, unknown, downloadSize, narSize); | ||||||
|  | 
 | ||||||
|  |         if (settings.printMissing) | ||||||
|  |             printMissing(ref<Store>(store), willBuild, willSubstitute, unknown, downloadSize, narSize); | ||||||
|  | 
 | ||||||
|  |         if (!dryRun) | ||||||
|  |             store->buildPaths(paths, buildMode); | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     if (runEnv) { |     if (runEnv) { | ||||||
|                 if (drvPaths.size() != 1) |         if (drvs.size() != 1) | ||||||
|                     throw UsageError("a single derivation is required"); |             throw UsageError("nix-shell requires a single derivation"); | ||||||
|                 auto drvPath = drvPaths[0]; |  | ||||||
|                 drvPath = drvPath.substr(0, drvPath.find_first_of('!')); |  | ||||||
|                 if (isLink(drvPath)) |  | ||||||
|                     drvPath = readLink(drvPath); |  | ||||||
|                 auto drv = store->derivationFromPath(drvPath); |  | ||||||
| 
 | 
 | ||||||
|                 // Build or fetch all dependencies of the derivation.
 |         auto & drvInfo = drvs.front(); | ||||||
|                 Strings nixStoreArgs{"-r", "--no-output", "--no-gc-warning"}; |         auto drv = store->derivationFromPath(drvInfo.queryDrvPath()); | ||||||
|                 for (const auto & arg : buildArgs) | 
 | ||||||
|                     nixStoreArgs.push_back(arg); |         PathSet pathsToBuild; | ||||||
|                 for (const auto & input : drv.inputDrvs) | 
 | ||||||
|                     if (std::all_of(envExclude.cbegin(), envExclude.cend(), [&](const string & exclude) { return !std::regex_search(input.first, std::regex(exclude)); })) |         /* Figure out what bash shell to use. If $NIX_BUILD_SHELL
 | ||||||
|                         nixStoreArgs.push_back(input.first); |            is not set, then build bashInteractive from | ||||||
|                 for (const auto & src : drv.inputSrcs) |            <nixpkgs>. */ | ||||||
|                     nixStoreArgs.push_back(src); |         auto shell = getEnv("NIX_BUILD_SHELL", ""); | ||||||
|  | 
 | ||||||
|  |         if (shell == "") { | ||||||
| 
 | 
 | ||||||
|             try { |             try { | ||||||
|                     runProgram(settings.nixBinDir + "/nix-store", false, nixStoreArgs); |                 auto expr = state.parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath(".")); | ||||||
|                 } catch (ExecError & e) { | 
 | ||||||
|                     maybePrintExecError(e); |                 Value v; | ||||||
|  |                 state.eval(expr, v); | ||||||
|  | 
 | ||||||
|  |                 auto drv = getDerivation(state, v, false); | ||||||
|  |                 if (!drv) | ||||||
|  |                     throw Error("the ‘bashInteractive’ attribute in <nixpkgs> did not evaluate to a derivation"); | ||||||
|  | 
 | ||||||
|  |                 pathsToBuild.insert(drv->queryDrvPath()); | ||||||
|  | 
 | ||||||
|  |                 shell = drv->queryOutPath() + "/bin/bash"; | ||||||
|  | 
 | ||||||
|  |             } catch (Error & e) { | ||||||
|  |                 printError("warning: %s; will use bash from your environment", e.what()); | ||||||
|  |                 shell = "bash"; | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Build or fetch all dependencies of the derivation.
 | ||||||
|  |         for (const auto & input : drv.inputDrvs) | ||||||
|  |             if (std::all_of(envExclude.cbegin(), envExclude.cend(), [&](const string & exclude) { return !std::regex_search(input.first, std::regex(exclude)); })) | ||||||
|  |                 pathsToBuild.insert(input.first); | ||||||
|  |         for (const auto & src : drv.inputSrcs) | ||||||
|  |             pathsToBuild.insert(src); | ||||||
|  | 
 | ||||||
|  |         buildPaths(pathsToBuild); | ||||||
| 
 | 
 | ||||||
|         if (dryRun) return; |         if (dryRun) return; | ||||||
| 
 | 
 | ||||||
|  | @ -436,10 +396,10 @@ int main(int argc, char ** argv) | ||||||
| 
 | 
 | ||||||
|         restoreAffinity(); |         restoreAffinity(); | ||||||
| 
 | 
 | ||||||
|                 // Run a shell using the derivation's environment.  For
 |         /* Run a shell using the derivation's environment.  For
 | ||||||
|                 // convenience, source $stdenv/setup to setup additional
 |            convenience, source $stdenv/setup to setup additional | ||||||
|                 // environment variables and shell functions.  Also don't lose
 |            environment variables and shell functions.  Also don't | ||||||
|                 // the current $PATH directories.
 |            lose the current $PATH directories. */ | ||||||
|         auto rcfile = (Path) tmpDir + "/rc"; |         auto rcfile = (Path) tmpDir + "/rc"; | ||||||
|         writeFile(rcfile, fmt( |         writeFile(rcfile, fmt( | ||||||
|                 (keepTmp ? "" : "rm -rf '%1%'; "s) + |                 (keepTmp ? "" : "rm -rf '%1%'; "s) + | ||||||
|  | @ -472,43 +432,6 @@ int main(int argc, char ** argv) | ||||||
| 
 | 
 | ||||||
|         auto envPtrs = stringsToCharPtrs(envStrs); |         auto envPtrs = stringsToCharPtrs(envStrs); | ||||||
| 
 | 
 | ||||||
|                 auto shell = getEnv("NIX_BUILD_SHELL", ""); |  | ||||||
| 
 |  | ||||||
|                 if (shell == "") { |  | ||||||
| 
 |  | ||||||
|                     try { |  | ||||||
| 
 |  | ||||||
|                         auto expr = state.parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath(".")); |  | ||||||
| 
 |  | ||||||
|                         Value v; |  | ||||||
|                         state.eval(expr, v); |  | ||||||
| 
 |  | ||||||
|                         auto drv = getDerivation(state, v, false); |  | ||||||
|                         if (!drv) |  | ||||||
|                             throw Error("the ‘bashInteractive’ attribute in <nixpkgs> did not evaluate to a derivation"); |  | ||||||
| 
 |  | ||||||
|                         auto drvPath = drv->queryDrvPath(); |  | ||||||
| 
 |  | ||||||
|                         unsigned long long downloadSize, narSize; |  | ||||||
|                         PathSet willBuild, willSubstitute, unknown; |  | ||||||
|                         store->queryMissing({drvPath}, |  | ||||||
|                             willBuild, willSubstitute, unknown, downloadSize, narSize); |  | ||||||
| 
 |  | ||||||
|                         if (settings.printMissing) |  | ||||||
|                             printMissing(ref<Store>(store), willBuild, willSubstitute, unknown, downloadSize, narSize); |  | ||||||
| 
 |  | ||||||
|                         store->buildPaths({drvPath}); |  | ||||||
| 
 |  | ||||||
|                         shell = drv->queryOutPath() + "/bin/bash"; |  | ||||||
|                         if (!pathExists(shell)) |  | ||||||
|                             throw Error("expected shell ‘%s’ to exist, but it doesn't", shell); |  | ||||||
| 
 |  | ||||||
|                     } catch (Error & e) { |  | ||||||
|                         printError("warning: %s; will use bash from your environment", e.what()); |  | ||||||
|                         shell = "bash"; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|         environ = envPtrs.data(); |         environ = envPtrs.data(); | ||||||
| 
 | 
 | ||||||
|         auto argPtrs = stringsToCharPtrs(args); |         auto argPtrs = stringsToCharPtrs(args); | ||||||
|  | @ -520,55 +443,58 @@ int main(int argc, char ** argv) | ||||||
|         throw SysError("executing shell ‘%s’", shell); |         throw SysError("executing shell ‘%s’", shell); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|             // Ugly hackery to make "nix-build -A foo.all" produce symlinks
 |     else { | ||||||
|             // ./result, ./result-dev, and so on, rather than ./result,
 |  | ||||||
|             // ./result-2-dev, and so on.  This combines multiple derivation
 |  | ||||||
|             // paths into one "/nix/store/drv-path!out1,out2,..." argument.
 |  | ||||||
|             std::string prevDrvPath; |  | ||||||
|             Strings drvPaths2; |  | ||||||
|             for (const auto & drvPath : drvPaths) { |  | ||||||
|                 auto p = drvPath; |  | ||||||
|                 std::string output = "out"; |  | ||||||
|                 std::smatch match; |  | ||||||
|                 if (std::regex_match(drvPath, match, std::regex("(.*)!(.*)"))) { |  | ||||||
|                     p = match[1].str(); |  | ||||||
|                     output = match[2].str(); |  | ||||||
|                 } |  | ||||||
|                 auto target = readLink(p); |  | ||||||
|                 if (verbose) |  | ||||||
|                     std::cerr << "derivation is " << target << '\n'; |  | ||||||
|                 if (target == prevDrvPath) { |  | ||||||
|                     auto last = drvPaths2.back(); |  | ||||||
|                     drvPaths2.pop_back(); |  | ||||||
|                     drvPaths2.push_back(last + "," + output); |  | ||||||
|                 } else { |  | ||||||
|                     drvPaths2.push_back(target + "!" + output); |  | ||||||
|                     prevDrvPath = target; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             // Build.
 |  | ||||||
|             Strings outPaths; |  | ||||||
|             Strings nixStoreArgs{"--add-root", outLink, "--indirect", "-r"}; |  | ||||||
|             for (const auto & arg : buildArgs) |  | ||||||
|                 nixStoreArgs.push_back(arg); |  | ||||||
|             for (const auto & path : drvPaths2) |  | ||||||
|                 nixStoreArgs.push_back(path); |  | ||||||
| 
 | 
 | ||||||
|             std::string nixStoreRes; |         PathSet pathsToBuild; | ||||||
|             try { | 
 | ||||||
|                 nixStoreRes = runProgram(settings.nixBinDir + "/nix-store", false, nixStoreArgs); |         std::map<Path, Path> drvPrefixes; | ||||||
|             } catch (ExecError & e) { |         std::map<Path, Path> resultSymlinks; | ||||||
|                 maybePrintExecError(e); |         std::vector<Path> outPaths; | ||||||
|  | 
 | ||||||
|  |         for (auto & drvInfo : drvs) { | ||||||
|  |             auto drvPath = drvInfo.queryDrvPath(); | ||||||
|  |             pathsToBuild.insert(drvPath); | ||||||
|  | 
 | ||||||
|  |             auto outputName = drvInfo.queryOutputName(); | ||||||
|  |             if (outputName == "") | ||||||
|  |                 throw Error("derivation ‘%s’ lacks an ‘outputName’ attribute", drvPath); | ||||||
|  | 
 | ||||||
|  |             pathsToBuild.insert(drvPath + (outputName != "out" ? "!" + outputName : "")); | ||||||
|  | 
 | ||||||
|  |             std::string drvPrefix; | ||||||
|  |             auto i = drvPrefixes.find(drvPath); | ||||||
|  |             if (i != drvPrefixes.end()) | ||||||
|  |                 drvPrefix = i->second; | ||||||
|  |             else { | ||||||
|  |                 drvPrefix = outLink; | ||||||
|  |                 if (drvPrefixes.size()) | ||||||
|  |                     drvPrefix += fmt("-%d", drvPrefixes.size() + 1); | ||||||
|  |                 drvPrefixes[drvPath] = drvPrefix; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (const auto & outpath : tokenizeString<std::vector<string>>(nixStoreRes)) |             std::string symlink = drvPrefix; | ||||||
|                 outPaths.push_back(chomp(outpath)); |             if (outputName != "out") symlink += "-" + outputName; | ||||||
| 
 | 
 | ||||||
|             if (dryRun) |             resultSymlinks[symlink] = drvInfo.queryOutPath(); | ||||||
|                 continue; |             outPaths.push_back(drvInfo.queryOutPath()); | ||||||
| 
 |  | ||||||
|             for (const auto & outPath : outPaths) |  | ||||||
|                 std::cout << readLink(outPath) << '\n'; |  | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         buildPaths(pathsToBuild); | ||||||
|  | 
 | ||||||
|  |         if (dryRun) return; | ||||||
|  | 
 | ||||||
|  |         for (auto & symlink : resultSymlinks) | ||||||
|  |             if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>()) | ||||||
|  |                 store2->addPermRoot(symlink.second, absPath(symlink.first), true); | ||||||
|  | 
 | ||||||
|  |         for (auto & path : outPaths) | ||||||
|  |             std::cout << path << '\n'; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main(int argc, char * * argv) | ||||||
|  | { | ||||||
|  |     return handleExceptions(argv[0], [&]() { | ||||||
|  |         return mainWrapped(argc, argv); | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,13 +17,6 @@ | ||||||
| using namespace nix; | using namespace nix; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static Expr * parseStdin(EvalState & state) |  | ||||||
| { |  | ||||||
|     //Activity act(*logger, lvlTalkative, format("parsing standard input"));
 |  | ||||||
|     return state.parseExprFromString(drainFD(0), absPath(".")); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static Path gcRoot; | static Path gcRoot; | ||||||
| static int rootNr = 0; | static int rootNr = 0; | ||||||
| static bool indirectRoot = false; | static bool indirectRoot = false; | ||||||
|  | @ -166,7 +159,7 @@ int main(int argc, char * * argv) | ||||||
| 
 | 
 | ||||||
|         Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); |         Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); | ||||||
| 
 | 
 | ||||||
|         if (attrPaths.empty()) attrPaths.push_back(""); |         if (attrPaths.empty()) attrPaths = {""}; | ||||||
| 
 | 
 | ||||||
|         if (findFile) { |         if (findFile) { | ||||||
|             for (auto & i : files) { |             for (auto & i : files) { | ||||||
|  | @ -178,7 +171,7 @@ int main(int argc, char * * argv) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (readStdin) { |         if (readStdin) { | ||||||
|             Expr * e = parseStdin(state); |             Expr * e = state.parseStdin(); | ||||||
|             processExpr(state, attrPaths, parseOnly, strict, autoArgs, |             processExpr(state, attrPaths, parseOnly, strict, autoArgs, | ||||||
|                 evalOnly, outputKind, xmlOutputSourceLocation, e); |                 evalOnly, outputKind, xmlOutputSourceLocation, e); | ||||||
|         } else if (files.empty() && !fromArgs) |         } else if (files.empty() && !fromArgs) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue