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); | ||||
| 
 | ||||
|     Expr * parseStdin(); | ||||
| 
 | ||||
|     /* Evaluate an expression read from the given file to normal
 | ||||
|        form. */ | ||||
|     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) | ||||
| { | ||||
|     size_t pos = s.find('='); | ||||
|  |  | |||
|  | @ -222,7 +222,14 @@ struct LegacyArgs : public MixCommonArgs | |||
| void parseCmdLine(int argc, char * * argv, | ||||
|     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, | ||||
|     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); | ||||
| 
 | ||||
| /* Ugh.  No better place to put this. */ | ||||
|  |  | |||
|  | @ -5,8 +5,6 @@ | |||
| #include <sstream> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "store-api.hh" | ||||
| #include "globals.hh" | ||||
| #include "derivations.hh" | ||||
|  | @ -14,7 +12,10 @@ | |||
| #include "util.hh" | ||||
| #include "shared.hh" | ||||
| #include "eval.hh" | ||||
| #include "eval-inline.hh" | ||||
| #include "get-drvs.hh" | ||||
| #include "common-opts.hh" | ||||
| #include "attr-path.hh" | ||||
| 
 | ||||
| using namespace nix; | ||||
| using namespace std::string_literals; | ||||
|  | @ -65,34 +66,26 @@ std::vector<string> shellwords(const string & s) | |||
|     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(); | ||||
|     initGC(); | ||||
| 
 | ||||
|         auto store = openStore(); | ||||
|     auto dryRun = false; | ||||
|         auto verbose = false; | ||||
|     auto runEnv = std::regex_search(argv[0], std::regex("nix-shell$")); | ||||
|     auto pure = false; | ||||
|     auto fromArgs = false; | ||||
|     auto packages = false; | ||||
|     // Same condition as bash uses for interactive shells
 | ||||
|     auto interactive = isatty(STDIN_FILENO) && isatty(STDERR_FILENO); | ||||
| 
 | ||||
|         Strings instArgs; | ||||
|         Strings buildArgs; | ||||
|         Strings exprs; | ||||
|     Strings attrPaths; | ||||
|     Strings left; | ||||
|     Strings searchPath; | ||||
|     std::map<string, string> autoArgs_; | ||||
|     RepairFlag repair = NoRepair; | ||||
|     Path gcRoot; | ||||
|     BuildMode buildMode = bmNormal; | ||||
|     bool readStdin = false; | ||||
| 
 | ||||
|     auto shell = getEnv("SHELL", "/bin/sh"); | ||||
|     std::string envCommand; // interactive shell
 | ||||
|  | @ -107,9 +100,8 @@ int main(int argc, char ** argv) | |||
|     AutoDelete tmpDir(createTempDir("", myName)); | ||||
| 
 | ||||
|     std::string outLink = "./result"; | ||||
|         auto drvLink = (Path) tmpDir + "/derivation"; | ||||
| 
 | ||||
|         std::vector<string> args; | ||||
|     Strings args; | ||||
|     for (int i = 1; i < argc; ++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) { | ||||
|             auto arg = args[n]; | ||||
| 
 | ||||
|             if (arg == "--help") { | ||||
|     parseCmdLine(myName, args, [&](Strings::iterator & arg, const Strings::iterator & end) { | ||||
|         if (*arg == "--help") { | ||||
|             deletePath(tmpDir); | ||||
|             showManPage(myName); | ||||
|         } | ||||
| 
 | ||||
|             else if (arg == "--version") | ||||
|         else if (*arg == "--version") | ||||
|             printVersion(myName); | ||||
| 
 | ||||
|             else if (arg == "--add-drv-link") { | ||||
|                 drvLink = "./derivation"; | ||||
|             } | ||||
|         else if (*arg == "--add-drv-link") | ||||
|             ; // obsolete
 | ||||
| 
 | ||||
|             else if (arg == "--no-out-link" || arg == "--no-link") { | ||||
|         else if (*arg == "--no-out-link" || *arg == "--no-link") | ||||
|             outLink = (Path) tmpDir + "/result"; | ||||
|             } | ||||
| 
 | ||||
|             else if (arg == "--drv-link") { | ||||
|                 n++; | ||||
|                 if (n >= args.size()) { | ||||
|                     throw UsageError("--drv-link requires an argument"); | ||||
|                 } | ||||
|                 drvLink = args[n]; | ||||
|             } | ||||
|         else if (*arg == "--attr" || *arg == "-A") | ||||
|             attrPaths.push_back(getArg(*arg, arg, end)); | ||||
| 
 | ||||
|             else if (arg == "--out-link" || arg == "-o") { | ||||
|                 n++; | ||||
|                 if (n >= args.size()) { | ||||
|                     throw UsageError(format("%1% requires an argument") % arg); | ||||
|                 } | ||||
|                 outLink = args[n]; | ||||
|             } | ||||
|         else if (*arg == "--drv-link") | ||||
|             getArg(*arg, arg, end); // obsolete
 | ||||
| 
 | ||||
|             else if (arg == "--attr" || arg == "-A" || arg == "-I") { | ||||
|                 n++; | ||||
|                 if (n >= args.size()) { | ||||
|                     throw UsageError(format("%1% requires an argument") % arg); | ||||
|                 } | ||||
|                 instArgs.push_back(arg); | ||||
|                 instArgs.push_back(args[n]); | ||||
|             } | ||||
|         else if (*arg == "--out-link" || *arg == "-o") | ||||
|             outLink = getArg(*arg, arg, end); | ||||
| 
 | ||||
|             else if (arg == "--arg" || arg == "--argstr") { | ||||
|                 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 (parseAutoArgs(arg, end, autoArgs_)) | ||||
|             ; | ||||
| 
 | ||||
|             else if (arg == "--option") { | ||||
|                 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 (parseSearchPathArg(arg, end, searchPath)) | ||||
|             ; | ||||
| 
 | ||||
|             else if (arg == "--max-jobs" || arg == "-j" || arg == "--max-silent-time" || arg == "--cores" || arg == "--timeout" || arg == "--add-root") { | ||||
|                 n++; | ||||
|                 if (n >= args.size()) { | ||||
|                     throw UsageError(format("%1% requires an argument") % arg); | ||||
|                 } | ||||
|                 buildArgs.push_back(arg); | ||||
|                 buildArgs.push_back(args[n]); | ||||
|             } | ||||
|         else if (*arg == "--add-root") | ||||
|             gcRoot = getArg(*arg, arg, end); | ||||
| 
 | ||||
|             else if (arg == "--dry-run") { | ||||
|                 buildArgs.push_back("--dry-run"); | ||||
|         else if (*arg == "--dry-run") | ||||
|             dryRun = true; | ||||
| 
 | ||||
|         else if (*arg == "--repair") { | ||||
|             repair = Repair; | ||||
|             buildMode = bmRepair; | ||||
|         } | ||||
| 
 | ||||
|             else if (arg == "--show-trace") { | ||||
|                 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
 | ||||
|         else if (*arg == "--run-env") // obsolete
 | ||||
|             runEnv = true; | ||||
|             } | ||||
| 
 | ||||
|             else if (arg == "--command" || arg == "--run") { | ||||
|                 n++; | ||||
|                 if (n >= args.size()) { | ||||
|                     throw UsageError(format("%1% requires an argument") % arg); | ||||
|                 } | ||||
|                 envCommand = args[n] + "\nexit"; | ||||
|                 if (arg == "--run") | ||||
|         else if (*arg == "--command" || *arg == "--run") { | ||||
|             if (*arg == "--run") | ||||
|                 interactive = false; | ||||
|             envCommand = getArg(*arg, arg, end) + "\nexit"; | ||||
|         } | ||||
| 
 | ||||
|             else if (arg == "--exclude") { | ||||
|                 n++; | ||||
|                 if (n >= args.size()) { | ||||
|                     throw UsageError(format("%1% requires an argument") % arg); | ||||
|                 } | ||||
|                 envExclude.push_back(args[n]); | ||||
|             } | ||||
|         else if (*arg == "--check") | ||||
|             buildMode = bmCheck; | ||||
| 
 | ||||
|             else if (arg == "--pure") { pure = true; } | ||||
|             else if (arg == "--impure") { pure = false; } | ||||
|         else if (*arg == "--exclude") | ||||
|             envExclude.push_back(getArg(*arg, arg, end)); | ||||
| 
 | ||||
|             else if (arg == "--expr" || arg == "-E") { | ||||
|         else if (*arg == "--expr" || *arg == "-E") | ||||
|             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; | ||||
|             } | ||||
| 
 | ||||
|             else if (inShebang && arg == "-i") { | ||||
|                 n++; | ||||
|                 if (n >= args.size()) { | ||||
|                     throw UsageError(format("%1% requires an argument") % arg); | ||||
|                 } | ||||
|         else if (inShebang && *arg == "-i") { | ||||
|             auto interpreter = getArg(*arg, arg, end); | ||||
|             interactive = false; | ||||
|                 auto interpreter = args[n]; | ||||
|             auto execArgs = ""; | ||||
| 
 | ||||
|             auto shellEscape = [](const string & s) { | ||||
|  | @ -311,91 +225,137 @@ int main(int argc, char ** argv) | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|             else if (!arg.empty() && arg[0] == '-') { | ||||
|                 buildArgs.push_back(arg); | ||||
|             } | ||||
|         else if (*arg == "-") | ||||
|             readStdin = true; | ||||
| 
 | ||||
|             else if (arg == "-Q" || arg == "--no-build-output") { | ||||
|                 buildArgs.push_back(arg); | ||||
|                 instArgs.push_back(arg); | ||||
|             } | ||||
|         else if (*arg != "" && arg->at(0) == '-') | ||||
|             return false; | ||||
| 
 | ||||
|             else { | ||||
|                 exprs.push_back(arg); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|             left.push_back(*arg); | ||||
| 
 | ||||
|         return true; | ||||
|     }); | ||||
| 
 | ||||
|     if (packages && fromArgs) | ||||
|         throw UsageError("‘-p’ and ‘-E’ are mutually exclusive"); | ||||
| 
 | ||||
|     auto store = openStore(); | ||||
| 
 | ||||
|     EvalState state(searchPath, store); | ||||
|     state.repair = repair; | ||||
| 
 | ||||
|         if (packages && fromArgs) { | ||||
|             throw UsageError("‘-p’ and ‘-E’ are mutually exclusive"); | ||||
|         } | ||||
|     Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); | ||||
| 
 | ||||
|     if (packages) { | ||||
|             instArgs.push_back("--expr"); | ||||
|         std::ostringstream joined; | ||||
|         joined << "with import <nixpkgs> { }; (pkgs.runCommandCC or pkgs.runCommand) \"shell\" { buildInputs = [ "; | ||||
|             for (const auto & i : exprs) | ||||
|         for (const auto & i : left) | ||||
|             joined << '(' << i << ") "; | ||||
|         joined << "]; } \"\""; | ||||
|             exprs = Strings{joined.str()}; | ||||
|         fromArgs = true; | ||||
|         left = {joined.str()}; | ||||
|     } else if (!fromArgs) { | ||||
|             if (exprs.empty() && runEnv && access("shell.nix", F_OK) == 0) | ||||
|                 exprs.push_back("shell.nix"); | ||||
|             if (exprs.empty()) | ||||
|                 exprs.push_back("default.nix"); | ||||
|         if (left.empty() && runEnv && pathExists("shell.nix")) | ||||
|             left = {"shell.nix"}; | ||||
|         if (left.empty()) | ||||
|             left = {"default.nix"}; | ||||
|     } | ||||
| 
 | ||||
|     if (runEnv) | ||||
|         setenv("IN_NIX_SHELL", pure ? "pure" : "impure", 1); | ||||
| 
 | ||||
|         for (auto & expr : exprs) { | ||||
|             // Instantiate.
 | ||||
|             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)); | ||||
|     /* Parse the expressions. */ | ||||
|     std::vector<Expr *> exprs; | ||||
| 
 | ||||
|                 Strings instantiateArgs{"--add-root", drvLink, "--indirect"}; | ||||
|                 for (const auto & arg : instArgs) | ||||
|                     instantiateArgs.push_back(arg); | ||||
|                 instantiateArgs.push_back(expr); | ||||
|                 try { | ||||
|                     auto instOutput = runProgram(settings.nixBinDir + "/nix-instantiate", false, instantiateArgs); | ||||
|                     drvPaths = tokenizeString<std::vector<string>>(instOutput); | ||||
|                 } catch (ExecError & e) { | ||||
|                     maybePrintExecError(e); | ||||
|     if (readStdin) | ||||
|         exprs = {state.parseStdin()}; | ||||
|     else | ||||
|         for (auto i : left) { | ||||
|             if (fromArgs) | ||||
|                 exprs.push_back(state.parseExprFromString(i, absPath("."))); | ||||
|             else | ||||
|                 /* If we're in a #! script, interpret filenames
 | ||||
|                    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 (drvPaths.size() != 1) | ||||
|                     throw UsageError("a single derivation is required"); | ||||
|                 auto drvPath = drvPaths[0]; | ||||
|                 drvPath = drvPath.substr(0, drvPath.find_first_of('!')); | ||||
|                 if (isLink(drvPath)) | ||||
|                     drvPath = readLink(drvPath); | ||||
|                 auto drv = store->derivationFromPath(drvPath); | ||||
|         if (drvs.size() != 1) | ||||
|             throw UsageError("nix-shell requires a single derivation"); | ||||
| 
 | ||||
|                 // Build or fetch all dependencies of the derivation.
 | ||||
|                 Strings nixStoreArgs{"-r", "--no-output", "--no-gc-warning"}; | ||||
|                 for (const auto & arg : buildArgs) | ||||
|                     nixStoreArgs.push_back(arg); | ||||
|                 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)); })) | ||||
|                         nixStoreArgs.push_back(input.first); | ||||
|                 for (const auto & src : drv.inputSrcs) | ||||
|                     nixStoreArgs.push_back(src); | ||||
|         auto & drvInfo = drvs.front(); | ||||
|         auto drv = store->derivationFromPath(drvInfo.queryDrvPath()); | ||||
| 
 | ||||
|         PathSet pathsToBuild; | ||||
| 
 | ||||
|         /* Figure out what bash shell to use. If $NIX_BUILD_SHELL
 | ||||
|            is not set, then build bashInteractive from | ||||
|            <nixpkgs>. */ | ||||
|         auto shell = getEnv("NIX_BUILD_SHELL", ""); | ||||
| 
 | ||||
|         if (shell == "") { | ||||
| 
 | ||||
|             try { | ||||
|                     runProgram(settings.nixBinDir + "/nix-store", false, nixStoreArgs); | ||||
|                 } catch (ExecError & e) { | ||||
|                     maybePrintExecError(e); | ||||
|                 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"); | ||||
| 
 | ||||
|                 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; | ||||
| 
 | ||||
|  | @ -436,10 +396,10 @@ int main(int argc, char ** argv) | |||
| 
 | ||||
|         restoreAffinity(); | ||||
| 
 | ||||
|                 // Run a shell using the derivation's environment.  For
 | ||||
|                 // convenience, source $stdenv/setup to setup additional
 | ||||
|                 // environment variables and shell functions.  Also don't lose
 | ||||
|                 // the current $PATH directories.
 | ||||
|         /* Run a shell using the derivation's environment.  For
 | ||||
|            convenience, source $stdenv/setup to setup additional | ||||
|            environment variables and shell functions.  Also don't | ||||
|            lose the current $PATH directories. */ | ||||
|         auto rcfile = (Path) tmpDir + "/rc"; | ||||
|         writeFile(rcfile, fmt( | ||||
|                 (keepTmp ? "" : "rm -rf '%1%'; "s) + | ||||
|  | @ -472,43 +432,6 @@ int main(int argc, char ** argv) | |||
| 
 | ||||
|         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(); | ||||
| 
 | ||||
|         auto argPtrs = stringsToCharPtrs(args); | ||||
|  | @ -520,55 +443,58 @@ int main(int argc, char ** argv) | |||
|         throw SysError("executing shell ‘%s’", shell); | ||||
|     } | ||||
| 
 | ||||
|             // Ugly hackery to make "nix-build -A foo.all" produce symlinks
 | ||||
|             // ./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); | ||||
|     else { | ||||
| 
 | ||||
|             std::string nixStoreRes; | ||||
|             try { | ||||
|                 nixStoreRes = runProgram(settings.nixBinDir + "/nix-store", false, nixStoreArgs); | ||||
|             } catch (ExecError & e) { | ||||
|                 maybePrintExecError(e); | ||||
|         PathSet pathsToBuild; | ||||
| 
 | ||||
|         std::map<Path, Path> drvPrefixes; | ||||
|         std::map<Path, Path> resultSymlinks; | ||||
|         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)) | ||||
|                 outPaths.push_back(chomp(outpath)); | ||||
|             std::string symlink = drvPrefix; | ||||
|             if (outputName != "out") symlink += "-" + outputName; | ||||
| 
 | ||||
|             if (dryRun) | ||||
|                 continue; | ||||
| 
 | ||||
|             for (const auto & outPath : outPaths) | ||||
|                 std::cout << readLink(outPath) << '\n'; | ||||
|             resultSymlinks[symlink] = drvInfo.queryOutPath(); | ||||
|             outPaths.push_back(drvInfo.queryOutPath()); | ||||
|         } | ||||
| 
 | ||||
|         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; | ||||
| 
 | ||||
| 
 | ||||
| static Expr * parseStdin(EvalState & state) | ||||
| { | ||||
|     //Activity act(*logger, lvlTalkative, format("parsing standard input"));
 | ||||
|     return state.parseExprFromString(drainFD(0), absPath(".")); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Path gcRoot; | ||||
| static int rootNr = 0; | ||||
| static bool indirectRoot = false; | ||||
|  | @ -166,7 +159,7 @@ int main(int argc, char * * argv) | |||
| 
 | ||||
|         Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); | ||||
| 
 | ||||
|         if (attrPaths.empty()) attrPaths.push_back(""); | ||||
|         if (attrPaths.empty()) attrPaths = {""}; | ||||
| 
 | ||||
|         if (findFile) { | ||||
|             for (auto & i : files) { | ||||
|  | @ -178,7 +171,7 @@ int main(int argc, char * * argv) | |||
|         } | ||||
| 
 | ||||
|         if (readStdin) { | ||||
|             Expr * e = parseStdin(state); | ||||
|             Expr * e = state.parseStdin(); | ||||
|             processExpr(state, attrPaths, parseOnly, strict, autoArgs, | ||||
|                 evalOnly, outputKind, xmlOutputSourceLocation, e); | ||||
|         } else if (files.empty() && !fromArgs) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue