From c94f3d5575d7af5403274d1e9e2f3c9d72989751 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 20 Jul 2017 13:32:01 +0200 Subject: [PATCH] nix-shell: Use bashInteractive from This adds about 0.1s to nix-shell runtime in the case where bashInteractive already exists. See discussion at https://github.com/NixOS/nixpkgs/issues/27493. --- src/libexpr/get-drvs.cc | 7 +++--- src/libexpr/get-drvs.hh | 8 +++---- src/nix-build/local.mk | 2 +- src/nix-build/nix-build.cc | 44 +++++++++++++++++++++++++++++++++++++- src/nix/repl.cc | 6 +++--- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index b7e16de7f..66689e3e8 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -267,15 +267,14 @@ static bool getDerivation(EvalState & state, Value & v, } -bool getDerivation(EvalState & state, Value & v, DrvInfo & drv, +std::experimental::optional getDerivation(EvalState & state, Value & v, bool ignoreAssertionFailures) { Done done; DrvInfos drvs; getDerivation(state, v, "", drvs, done, ignoreAssertionFailures); - if (drvs.size() != 1) return false; - drv = drvs.front(); - return true; + if (drvs.size() != 1) return {}; + return std::move(drvs.front()); } diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index 82fb8a3ac..32294e458 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -75,10 +75,10 @@ typedef list DrvInfos; #endif -/* If value `v' denotes a derivation, store information about the - derivation in `drv' and return true. Otherwise, return false. */ -bool getDerivation(EvalState & state, Value & v, DrvInfo & drv, - bool ignoreAssertionFailures); +/* If value `v' denotes a derivation, return a DrvInfo object + describing it. Otherwise return nothing. */ +std::experimental::optional getDerivation(EvalState & state, + Value & v, bool ignoreAssertionFailures); void getDerivations(EvalState & state, Value & v, const string & pathPrefix, Bindings & autoArgs, DrvInfos & drvs, diff --git a/src/nix-build/local.mk b/src/nix-build/local.mk index 91532411a..a2d1c91df 100644 --- a/src/nix-build/local.mk +++ b/src/nix-build/local.mk @@ -4,6 +4,6 @@ nix-build_DIR := $(d) nix-build_SOURCES := $(d)/nix-build.cc -nix-build_LIBS = libmain libstore libutil libformat +nix-build_LIBS = libmain libexpr libstore libutil libformat $(eval $(call install-symlink, nix-build, $(bindir)/nix-shell)) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index dc80dd6a5..72f89003d 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -13,6 +13,8 @@ #include "affinity.hh" #include "util.hh" #include "shared.hh" +#include "eval.hh" +#include "get-drvs.hh" using namespace nix; using namespace std::string_literals; @@ -75,6 +77,8 @@ int main(int argc, char ** argv) { return handleExceptions(argv[0], [&]() { initNix(); + initGC(); + auto store = openStore(); auto dryRun = false; auto verbose = false; @@ -88,6 +92,7 @@ int main(int argc, char ** argv) Strings instArgs; Strings buildArgs; Strings exprs; + Strings searchPath; auto shell = getEnv("SHELL", "/bin/sh"); std::string envCommand; // interactive shell @@ -320,6 +325,8 @@ int main(int argc, char ** argv) } } + EvalState state(searchPath, store); + if (packages && fromArgs) { throw UsageError("‘-p’ and ‘-E’ are mutually exclusive"); } @@ -465,7 +472,42 @@ int main(int argc, char ** argv) auto envPtrs = stringsToCharPtrs(envStrs); - auto shell = getEnv("NIX_BUILD_SHELL", "bash"); + auto shell = getEnv("NIX_BUILD_SHELL", ""); + + if (shell == "") { + + try { + + auto expr = state.parseExprFromString("(import {}).bashInteractive", absPath(".")); + + Value v; + state.eval(expr, v); + + auto drv = getDerivation(state, v, false); + if (!drv) + throw Error("the ‘bashInteractive’ attribute in 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), 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(); diff --git a/src/nix/repl.cc b/src/nix/repl.cc index 437c7903e..7d5b8f466 100644 --- a/src/nix/repl.cc +++ b/src/nix/repl.cc @@ -292,10 +292,10 @@ bool isVarName(const string & s) Path NixRepl::getDerivationPath(Value & v) { - DrvInfo drvInfo(state); - if (!getDerivation(state, v, drvInfo, false)) + auto drvInfo = getDerivation(state, v, false); + if (!drvInfo) throw Error("expression does not evaluate to a derivation, so I can't build it"); - Path drvPath = drvInfo.queryDrvPath(); + Path drvPath = drvInfo->queryDrvPath(); if (drvPath == "" || !state.store->isValidPath(drvPath)) throw Error("expression did not evaluate to a valid derivation"); return drvPath;