aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-07-20 13:32:01 +0200
committerEelco Dolstra <edolstra@gmail.com>2017-07-20 13:50:25 +0200
commitc94f3d5575d7af5403274d1e9e2f3c9d72989751 (patch)
treed6a302d585ed8f38a8a8d959b74bee44b7d77370
parent57a30e101b36a064f09619bf4a3f0b8a3fdcdcad (diff)
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.
-rw-r--r--src/libexpr/get-drvs.cc7
-rw-r--r--src/libexpr/get-drvs.hh8
-rw-r--r--src/nix-build/local.mk2
-rwxr-xr-xsrc/nix-build/nix-build.cc44
-rw-r--r--src/nix/repl.cc6
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<DrvInfo> 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<DrvInfo> 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<DrvInfo> 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 <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();
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;