From ca93b26db6d2d73e702ea8ecdd0a98f17ace2c7b Mon Sep 17 00:00:00 2001 From: Antoine Eiche Date: Wed, 29 Apr 2020 14:39:37 +0200 Subject: Only call grantpt on MacOS systems The commit 3cc1125595d97b4ab7369e37e4ad22f4cfecb8b2 adds a `grantpt` call on the builder pseudo terminal fd. This call is actually only required for MacOS, but it however requires a RW access to /dev/pts which is only RO bindmounted in the Bazel Linux sandbox. So, Nix can not be actually run in the Bazel Linux sandbox for unneeded reasons. --- src/libstore/build.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 572634765..147093fae 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -2250,10 +2250,13 @@ void DerivationGoal::startBuilder() if (chown(slaveName.c_str(), buildUser->getUID(), 0)) throw SysError("changing owner of pseudoterminal slave"); - } else { + } +#if __APPLE__ + else { if (grantpt(builderOut.readSide.get())) throw SysError("granting access to pseudoterminal slave"); } +#endif #if 0 // Mount the pt in the sandbox so that the "tty" command works. -- cgit v1.2.3 From d1229859c2612587bfd04111bae6584c0c9df051 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Wed, 29 Apr 2020 22:48:29 +0200 Subject: Fix displaying error-position in `builtins.fetch{Tree,Tarball}` Without dereferencing this pointer, you'd get an error like this: ``` error: unsupported argument 'abc' to 'fetchTarball', at 0x13627e8 ``` --- src/libexpr/primops/fetchTree.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index 43c58485a..c5a0d9886 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -108,7 +108,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, name = state.forceStringNoCtx(*attr.value, *attr.pos); else throw EvalError("unsupported argument '%s' to '%s', at %s", - attr.name, who, attr.pos); + attr.name, who, *attr.pos); } if (!url) -- cgit v1.2.3 From 2fcfc6c2c6ff144131d669ebfb2caa63c8b41417 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Apr 2020 13:05:29 +0200 Subject: nix dev-shell: Refactor script for getting the environment --- src/nix/get-env.sh | 8 ++++++++ src/nix/local.mk | 2 ++ src/nix/shell.cc | 18 ++++++++---------- 3 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 src/nix/get-env.sh (limited to 'src') diff --git a/src/nix/get-env.sh b/src/nix/get-env.sh new file mode 100644 index 000000000..782f97b75 --- /dev/null +++ b/src/nix/get-env.sh @@ -0,0 +1,8 @@ +set -e +export IN_NIX_SHELL=impure +export dontAddDisableDepTrack=1 +if [[ -n $stdenv ]]; then + source $stdenv/setup +fi +export > $out +set >> $out diff --git a/src/nix/local.mk b/src/nix/local.mk index 033675e89..15cef55bb 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -27,3 +27,5 @@ $(foreach name, \ $(eval $(call install-symlink, $(bindir)/nix, $(libexecdir)/nix/build-remote)) src/nix-env/user-env.cc: src/nix-env/buildenv.nix.gen.hh + +src/nix/shell.cc: src/nix/get-env.sh.gen.hh diff --git a/src/nix/shell.cc b/src/nix/shell.cc index fbfe24bbe..c8bf35a13 100644 --- a/src/nix/shell.cc +++ b/src/nix/shell.cc @@ -83,6 +83,10 @@ BuildEnvironment readEnvironment(const Path & path) return res; } +const static std::string getEnvSh = + #include "get-env.sh.gen.hh" + ; + /* Given an existing derivation, return the shell environment as initialised by stdenv's setup script. We do this by building a modified derivation with the same dependencies and nearly the same @@ -94,16 +98,9 @@ StorePath getDerivationEnvironment(ref store, Derivation drv) if (builder != "bash") throw Error("'nix dev-shell' only works on derivations that use 'bash' as their builder"); - drv.args = { - "-c", - "set -e; " - "export IN_NIX_SHELL=impure; " - "export dontAddDisableDepTrack=1; " - "if [[ -n $stdenv ]]; then " - " source $stdenv/setup; " - "fi; " - "export > $out; " - "set >> $out "}; + auto getEnvShPath = store->addTextToStore("get-env.sh", getEnvSh, {}); + + drv.args = {store->printStorePath(getEnvShPath)}; /* Remove derivation checks. */ drv.env.erase("allowedReferences"); @@ -120,6 +117,7 @@ StorePath getDerivationEnvironment(ref store, Derivation drv) drv.env.erase(output.first); drv.env["out"] = ""; drv.env["outputs"] = "out"; + drv.inputSrcs.insert(std::move(getEnvShPath)); Hash h = hashDerivationModulo(*store, drv, true); auto shellOutPath = store->makeOutputPath("out", h, drvName); drv.outputs.insert_or_assign("out", DerivationOutput(shellOutPath.clone(), "", "")); -- cgit v1.2.3 From efe6c186eabeb85830be7bef9aea4dd7eb2357e7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Apr 2020 14:39:26 +0200 Subject: nix dev-shell: Support structured attrs Tested against https://github.com/NixOS/nixpkgs/pull/72074. Fixes #3540. --- src/nix/get-env.sh | 1 + src/nix/shell.cc | 45 ++++++++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nix/get-env.sh b/src/nix/get-env.sh index 782f97b75..a25ec43a9 100644 --- a/src/nix/get-env.sh +++ b/src/nix/get-env.sh @@ -1,4 +1,5 @@ set -e +if [ -e .attrs.sh ]; then source .attrs.sh; fi export IN_NIX_SHELL=impure export dontAddDisableDepTrack=1 if [[ -n $stdenv ]]; then diff --git a/src/nix/shell.cc b/src/nix/shell.cc index c8bf35a13..f0ffceaa7 100644 --- a/src/nix/shell.cc +++ b/src/nix/shell.cc @@ -13,7 +13,8 @@ using namespace nix; struct Var { - bool exported; + bool exported = true; + bool associative = false; std::string value; // quoted string or array }; @@ -48,11 +49,17 @@ BuildEnvironment readEnvironment(const Path & path) static std::string quotedStringRegex = R"re((?:\$?'(?:[^'\\]|\\[abeEfnrtv\\'"?])*'))re"; - static std::string arrayRegex = - R"re((?:\(( *\[[^\]]+\]="(?:[^"\\]|\\.)*")*\)))re"; + static std::string indexedArrayRegex = + R"re((?:\(( *\[[0-9]+]="(?:[^"\\]|\\.)*")**\)))re"; static std::regex varRegex( - "^(" + varNameRegex + ")=(" + simpleStringRegex + "|" + quotedStringRegex + "|" + arrayRegex + ")\n"); + "^(" + varNameRegex + ")=(" + simpleStringRegex + "|" + quotedStringRegex + "|" + indexedArrayRegex + ")\n"); + + /* Note: we distinguish between an indexed and associative array + using the space before the closing parenthesis. Will + undoubtedly regret this some day. */ + static std::regex assocArrayRegex( + "^(" + varNameRegex + ")=" + R"re((?:\(( *\[[^\]]+\]="(?:[^"\\]|\\.)*")* *\)))re" + "\n"); static std::regex functionRegex( "^" + varNameRegex + " \\(\\) *\n"); @@ -68,7 +75,12 @@ BuildEnvironment readEnvironment(const Path & path) else if (std::regex_search(pos, file.cend(), match, varRegex)) { pos = match[0].second; - res.env.insert({match[1], Var { (bool) exported.count(match[1]), match[2] }}); + res.env.insert({match[1], Var { .exported = exported.count(match[1]) > 0, .value = match[2] }}); + } + + else if (std::regex_search(pos, file.cend(), match, assocArrayRegex)) { + pos = match[0].second; + res.env.insert({match[1], Var { .associative = true, .value = match[2] }}); } else if (std::regex_search(pos, file.cend(), match, functionRegex)) { @@ -92,8 +104,10 @@ const static std::string getEnvSh = modified derivation with the same dependencies and nearly the same initial environment variables, that just writes the resulting environment to a file and exits. */ -StorePath getDerivationEnvironment(ref store, Derivation drv) +StorePath getDerivationEnvironment(ref store, const StorePath & drvPath) { + auto drv = store->derivationFromPath(drvPath); + auto builder = baseNameOf(drv.builder); if (builder != "bash") throw Error("'nix dev-shell' only works on derivations that use 'bash' as their builder"); @@ -108,11 +122,12 @@ StorePath getDerivationEnvironment(ref store, Derivation drv) drv.env.erase("disallowedReferences"); drv.env.erase("disallowedRequisites"); - // FIXME: handle structured attrs - /* Rehash and write the derivation. FIXME: would be nice to use 'buildDerivation', but that's privileged. */ - auto drvName = drv.env["name"] + "-env"; + auto drvName = std::string(drvPath.name()); + assert(hasSuffix(drvName, ".drv")); + drvName.resize(drvName.size() - 4); + drvName += "-env"; for (auto & output : drv.outputs) drv.env.erase(output.first); drv.env["out"] = ""; @@ -161,9 +176,13 @@ struct Common : InstallableCommand, MixProfile for (auto & i : buildEnvironment.env) { if (!ignoreVars.count(i.first) && !hasPrefix(i.first, "BASH_")) { - out << fmt("%s=%s\n", i.first, i.second.value); - if (i.second.exported) - out << fmt("export %s\n", i.first); + if (i.second.associative) + out << fmt("declare -A %s=(%s)\n", i.first, i.second.value); + else { + out << fmt("%s=%s\n", i.first, i.second.value); + if (i.second.exported) + out << fmt("export %s\n", i.first); + } } } @@ -194,7 +213,7 @@ struct Common : InstallableCommand, MixProfile auto & drvPath = *drvs.begin(); - return getDerivationEnvironment(store, store->derivationFromPath(drvPath)); + return getDerivationEnvironment(store, drvPath); } } -- cgit v1.2.3 From 0135fd6ec4dcd15771008b867f28047e5c2bb605 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 30 Apr 2020 14:46:51 +0200 Subject: nix dev-shell: Unset shellHook This avoids inheriting the caller's shellHook, which can happen when running a dev-shell inside a dev-shell. --- src/nix/shell.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/nix/shell.cc b/src/nix/shell.cc index f0ffceaa7..9c45a935d 100644 --- a/src/nix/shell.cc +++ b/src/nix/shell.cc @@ -172,6 +172,8 @@ struct Common : InstallableCommand, MixProfile void makeRcScript(const BuildEnvironment & buildEnvironment, std::ostream & out) { + out << "unset shellHook\n"; + out << "nix_saved_PATH=\"$PATH\"\n"; for (auto & i : buildEnvironment.env) { -- cgit v1.2.3