diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2017-08-29T13·00+0200 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2017-08-29T13·00+0200 |
commit | 05d68a6e23127e490193599f75489006830b302c (patch) | |
tree | 213b0c677dec14868a0dadc40d0dadbf40562b7a | |
parent | 5cc8609e30ab4f76053f3159c51ea78d9215bc8c (diff) |
nix run: Add some flags for clearing/keeping the environment
This is useful for testing commands in isolation. For example, $ nix run nixpkgs.geeqie -i -k DISPLAY -k XAUTHORITY -c geeqie runs geeqie in an empty environment, except for $DISPLAY and $XAUTHORITY.
-rw-r--r-- | src/nix/run.cc | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/nix/run.cc b/src/nix/run.cc index 39fbcc8acf9f..8175d38e8ca6 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -18,6 +18,8 @@ std::string chrootHelperName = "__run_in_chroot"; struct CmdRun : InstallablesCommand { Strings command = { "bash" }; + StringSet keep, unset; + bool ignoreEnvironment = false; CmdRun() { @@ -31,6 +33,28 @@ struct CmdRun : InstallablesCommand if (ss.empty()) throw UsageError("--command requires at least one argument"); command = ss; }); + + mkFlag() + .longName("ignore-environment") + .shortName('i') + .description("clear the entire environment (except those specified with --keep)") + .handler([&](Strings ss) { ignoreEnvironment = true; }); + + mkFlag() + .longName("keep") + .shortName('k') + .description("keep specified environment variable") + .arity(1) + .labels({"name"}) + .handler([&](Strings ss) { keep.insert(ss.front()); }); + + mkFlag() + .longName("unset") + .shortName('u') + .description("unset specified environment variable") + .arity(1) + .labels({"name"}) + .handler([&](Strings ss) { unset.insert(ss.front()); }); } std::string name() override @@ -49,6 +73,31 @@ struct CmdRun : InstallablesCommand auto accessor = store->getFSAccessor(); + if (ignoreEnvironment) { + + if (!unset.empty()) + throw UsageError("--unset does not make sense with --ignore-environment"); + + std::map<std::string, std::string> kept; + for (auto & var : keep) { + auto s = getenv(var.c_str()); + if (s) kept[var] = s; + } + + clearenv(); + + for (auto & var : kept) + setenv(var.first.c_str(), var.second.c_str(), 1); + + } else { + + if (!keep.empty()) + throw UsageError("--keep does not make sense without --ignore-environment"); + + for (auto & var : unset) + unsetenv(var.c_str()); + } + auto unixPath = tokenizeString<Strings>(getEnv("PATH"), ":"); for (auto & path : outPaths) if (accessor->stat(path + "/bin").type != FSAccessor::tMissing) |