nix-shell: Use bashInteractive from <nixpkgs>

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.
This commit is contained in:
Eelco Dolstra 2017-07-20 13:32:01 +02:00
parent 57a30e101b
commit c94f3d5575
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
5 changed files with 54 additions and 13 deletions

View file

@ -267,15 +267,14 @@ static bool getDerivation(EvalState & state, Value & v,
} }
bool getDerivation(EvalState & state, Value & v, DrvInfo & drv, std::experimental::optional<DrvInfo> getDerivation(EvalState & state, Value & v,
bool ignoreAssertionFailures) bool ignoreAssertionFailures)
{ {
Done done; Done done;
DrvInfos drvs; DrvInfos drvs;
getDerivation(state, v, "", drvs, done, ignoreAssertionFailures); getDerivation(state, v, "", drvs, done, ignoreAssertionFailures);
if (drvs.size() != 1) return false; if (drvs.size() != 1) return {};
drv = drvs.front(); return std::move(drvs.front());
return true;
} }

View file

@ -75,10 +75,10 @@ typedef list<DrvInfo> DrvInfos;
#endif #endif
/* If value `v' denotes a derivation, store information about the /* If value `v' denotes a derivation, return a DrvInfo object
derivation in `drv' and return true. Otherwise, return false. */ describing it. Otherwise return nothing. */
bool getDerivation(EvalState & state, Value & v, DrvInfo & drv, std::experimental::optional<DrvInfo> getDerivation(EvalState & state,
bool ignoreAssertionFailures); Value & v, bool ignoreAssertionFailures);
void getDerivations(EvalState & state, Value & v, const string & pathPrefix, void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
Bindings & autoArgs, DrvInfos & drvs, Bindings & autoArgs, DrvInfos & drvs,

View file

@ -4,6 +4,6 @@ nix-build_DIR := $(d)
nix-build_SOURCES := $(d)/nix-build.cc 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)) $(eval $(call install-symlink, nix-build, $(bindir)/nix-shell))

View file

@ -13,6 +13,8 @@
#include "affinity.hh" #include "affinity.hh"
#include "util.hh" #include "util.hh"
#include "shared.hh" #include "shared.hh"
#include "eval.hh"
#include "get-drvs.hh"
using namespace nix; using namespace nix;
using namespace std::string_literals; using namespace std::string_literals;
@ -75,6 +77,8 @@ int main(int argc, char ** argv)
{ {
return handleExceptions(argv[0], [&]() { return handleExceptions(argv[0], [&]() {
initNix(); initNix();
initGC();
auto store = openStore(); auto store = openStore();
auto dryRun = false; auto dryRun = false;
auto verbose = false; auto verbose = false;
@ -88,6 +92,7 @@ int main(int argc, char ** argv)
Strings instArgs; Strings instArgs;
Strings buildArgs; Strings buildArgs;
Strings exprs; Strings exprs;
Strings searchPath;
auto shell = getEnv("SHELL", "/bin/sh"); auto shell = getEnv("SHELL", "/bin/sh");
std::string envCommand; // interactive shell std::string envCommand; // interactive shell
@ -320,6 +325,8 @@ int main(int argc, char ** argv)
} }
} }
EvalState state(searchPath, store);
if (packages && fromArgs) { if (packages && fromArgs) {
throw UsageError("-p and -E are mutually exclusive"); throw UsageError("-p and -E are mutually exclusive");
} }
@ -465,7 +472,42 @@ int main(int argc, char ** argv)
auto envPtrs = stringsToCharPtrs(envStrs); 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 <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();

View file

@ -292,10 +292,10 @@ bool isVarName(const string & s)
Path NixRepl::getDerivationPath(Value & v) { Path NixRepl::getDerivationPath(Value & v) {
DrvInfo drvInfo(state); auto drvInfo = getDerivation(state, v, false);
if (!getDerivation(state, v, drvInfo, false)) if (!drvInfo)
throw Error("expression does not evaluate to a derivation, so I can't build it"); 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)) if (drvPath == "" || !state.store->isValidPath(drvPath))
throw Error("expression did not evaluate to a valid derivation"); throw Error("expression did not evaluate to a valid derivation");
return drvPath; return drvPath;