mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-22 14:06:16 +02:00
nix env shell: Move from nix shell, add shorthand alias
This commit is contained in:
parent
98b85b2166
commit
c692f6af13
5 changed files with 114 additions and 77 deletions
12
doc/manual/rl-next/nix-env-shell.md
Normal file
12
doc/manual/rl-next/nix-env-shell.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
synopsis: "`nix env shell` is the new `nix shell`, and `nix shell` remains an accepted alias"
|
||||||
|
issues: 10504
|
||||||
|
prs: 10807
|
||||||
|
---
|
||||||
|
|
||||||
|
This is part of an effort to bring more structure to the CLI subcommands.
|
||||||
|
|
||||||
|
`nix env` will be about the process environment.
|
||||||
|
Future commands may include `nix env run` and `nix env print-env`.
|
||||||
|
|
||||||
|
It is also somewhat analogous to the [planned](https://github.com/NixOS/nix/issues/10504) `nix dev shell` (currently `nix develop`), which is less about environment variables, and more about running a development shell, which is a more powerful command, but also requires more setup.
|
98
src/nix/env.cc
Normal file
98
src/nix/env.cc
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#include "command.hh"
|
||||||
|
#include "run.hh"
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
using namespace nix;
|
||||||
|
|
||||||
|
struct CmdEnv : NixMultiCommand
|
||||||
|
{
|
||||||
|
CmdEnv() : NixMultiCommand("env", RegisterCommand::getCommandsFor({"env"}))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "manipulate the process environment";
|
||||||
|
}
|
||||||
|
|
||||||
|
Category category() override { return catUtility; }
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto rCmdEnv = registerCommand<CmdEnv>("env");
|
||||||
|
|
||||||
|
struct CmdShell : InstallablesCommand, MixEnvironment
|
||||||
|
{
|
||||||
|
|
||||||
|
using InstallablesCommand::run;
|
||||||
|
|
||||||
|
std::vector<std::string> command = { getEnv("SHELL").value_or("bash") };
|
||||||
|
|
||||||
|
CmdShell()
|
||||||
|
{
|
||||||
|
addFlag({
|
||||||
|
.longName = "command",
|
||||||
|
.shortName = 'c',
|
||||||
|
.description = "Command and arguments to be executed, defaulting to `$SHELL`",
|
||||||
|
.labels = {"command", "args"},
|
||||||
|
.handler = {[&](std::vector<std::string> ss) {
|
||||||
|
if (ss.empty()) throw UsageError("--command requires at least one argument");
|
||||||
|
command = ss;
|
||||||
|
}}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description() override
|
||||||
|
{
|
||||||
|
return "run a shell in which the specified packages are available";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string doc() override
|
||||||
|
{
|
||||||
|
return
|
||||||
|
#include "shell.md"
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(ref<Store> store, Installables && installables) override
|
||||||
|
{
|
||||||
|
auto outPaths = Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
|
||||||
|
|
||||||
|
auto accessor = store->getFSAccessor();
|
||||||
|
|
||||||
|
std::unordered_set<StorePath> done;
|
||||||
|
std::queue<StorePath> todo;
|
||||||
|
for (auto & path : outPaths) todo.push(path);
|
||||||
|
|
||||||
|
setEnviron();
|
||||||
|
|
||||||
|
std::vector<std::string> pathAdditions;
|
||||||
|
|
||||||
|
while (!todo.empty()) {
|
||||||
|
auto path = todo.front();
|
||||||
|
todo.pop();
|
||||||
|
if (!done.insert(path).second) continue;
|
||||||
|
|
||||||
|
if (true)
|
||||||
|
pathAdditions.push_back(store->printStorePath(path) + "/bin");
|
||||||
|
|
||||||
|
auto propPath = accessor->resolveSymlinks(
|
||||||
|
CanonPath(store->printStorePath(path)) / "nix-support" / "propagated-user-env-packages");
|
||||||
|
if (auto st = accessor->maybeLstat(propPath); st && st->type == SourceAccessor::tRegular) {
|
||||||
|
for (auto & p : tokenizeString<Paths>(accessor->readFile(propPath)))
|
||||||
|
todo.push(store->parseStorePath(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto unixPath = tokenizeString<Strings>(getEnv("PATH").value_or(""), ":");
|
||||||
|
unixPath.insert(unixPath.begin(), pathAdditions.begin(), pathAdditions.end());
|
||||||
|
auto unixPathString = concatStringsSep(":", unixPath);
|
||||||
|
setEnv("PATH", unixPathString.c_str());
|
||||||
|
|
||||||
|
Strings args;
|
||||||
|
for (auto & arg : command) args.push_back(arg);
|
||||||
|
|
||||||
|
runProgramInStore(store, UseLookupPath::Use, *command.begin(), args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto rCmdShell = registerCommand2<CmdShell>({"env", "shell"});
|
||||||
|
|
|
@ -163,6 +163,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs, virtual RootArgs
|
||||||
{"optimise-store", { AliasStatus::Deprecated, {"store", "optimise"}}},
|
{"optimise-store", { AliasStatus::Deprecated, {"store", "optimise"}}},
|
||||||
{"ping-store", { AliasStatus::Deprecated, {"store", "ping"}}},
|
{"ping-store", { AliasStatus::Deprecated, {"store", "ping"}}},
|
||||||
{"sign-paths", { AliasStatus::Deprecated, {"store", "sign"}}},
|
{"sign-paths", { AliasStatus::Deprecated, {"store", "sign"}}},
|
||||||
|
{"shell", { AliasStatus::AcceptedShorthand, {"env", "shell"}}},
|
||||||
{"show-derivation", { AliasStatus::Deprecated, {"derivation", "show"}}},
|
{"show-derivation", { AliasStatus::Deprecated, {"derivation", "show"}}},
|
||||||
{"show-config", { AliasStatus::Deprecated, {"config", "show"}}},
|
{"show-config", { AliasStatus::Deprecated, {"config", "show"}}},
|
||||||
{"to-base16", { AliasStatus::Deprecated, {"hash", "to-base16"}}},
|
{"to-base16", { AliasStatus::Deprecated, {"hash", "to-base16"}}},
|
||||||
|
|
|
@ -71,83 +71,6 @@ void runProgramInStore(ref<Store> store,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CmdShell : InstallablesCommand, MixEnvironment
|
|
||||||
{
|
|
||||||
|
|
||||||
using InstallablesCommand::run;
|
|
||||||
|
|
||||||
std::vector<std::string> command = { getEnv("SHELL").value_or("bash") };
|
|
||||||
|
|
||||||
CmdShell()
|
|
||||||
{
|
|
||||||
addFlag({
|
|
||||||
.longName = "command",
|
|
||||||
.shortName = 'c',
|
|
||||||
.description = "Command and arguments to be executed, defaulting to `$SHELL`",
|
|
||||||
.labels = {"command", "args"},
|
|
||||||
.handler = {[&](std::vector<std::string> ss) {
|
|
||||||
if (ss.empty()) throw UsageError("--command requires at least one argument");
|
|
||||||
command = ss;
|
|
||||||
}}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string description() override
|
|
||||||
{
|
|
||||||
return "run a shell in which the specified packages are available";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string doc() override
|
|
||||||
{
|
|
||||||
return
|
|
||||||
#include "shell.md"
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void run(ref<Store> store, Installables && installables) override
|
|
||||||
{
|
|
||||||
auto outPaths = Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
|
|
||||||
|
|
||||||
auto accessor = store->getFSAccessor();
|
|
||||||
|
|
||||||
std::unordered_set<StorePath> done;
|
|
||||||
std::queue<StorePath> todo;
|
|
||||||
for (auto & path : outPaths) todo.push(path);
|
|
||||||
|
|
||||||
setEnviron();
|
|
||||||
|
|
||||||
std::vector<std::string> pathAdditions;
|
|
||||||
|
|
||||||
while (!todo.empty()) {
|
|
||||||
auto path = todo.front();
|
|
||||||
todo.pop();
|
|
||||||
if (!done.insert(path).second) continue;
|
|
||||||
|
|
||||||
if (true)
|
|
||||||
pathAdditions.push_back(store->printStorePath(path) + "/bin");
|
|
||||||
|
|
||||||
auto propPath = accessor->resolveSymlinks(
|
|
||||||
CanonPath(store->printStorePath(path)) / "nix-support" / "propagated-user-env-packages");
|
|
||||||
if (auto st = accessor->maybeLstat(propPath); st && st->type == SourceAccessor::tRegular) {
|
|
||||||
for (auto & p : tokenizeString<Paths>(accessor->readFile(propPath)))
|
|
||||||
todo.push(store->parseStorePath(p));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto unixPath = tokenizeString<Strings>(getEnv("PATH").value_or(""), ":");
|
|
||||||
unixPath.insert(unixPath.begin(), pathAdditions.begin(), pathAdditions.end());
|
|
||||||
auto unixPathString = concatStringsSep(":", unixPath);
|
|
||||||
setEnv("PATH", unixPathString.c_str());
|
|
||||||
|
|
||||||
Strings args;
|
|
||||||
for (auto & arg : command) args.push_back(arg);
|
|
||||||
|
|
||||||
runProgramInStore(store, UseLookupPath::Use, *command.begin(), args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static auto rCmdShell = registerCommand<CmdShell>("shell");
|
|
||||||
|
|
||||||
struct CmdRun : InstallableValueCommand
|
struct CmdRun : InstallableValueCommand
|
||||||
{
|
{
|
||||||
using InstallableCommand::run;
|
using InstallableCommand::run;
|
||||||
|
|
|
@ -5,6 +5,9 @@ source common.sh
|
||||||
clearStore
|
clearStore
|
||||||
clearCache
|
clearCache
|
||||||
|
|
||||||
|
# nix shell is an alias for nix env shell. We'll use the shorter form in the rest of the test.
|
||||||
|
nix env shell -f shell-hello.nix hello -c hello | grep 'Hello World'
|
||||||
|
|
||||||
nix shell -f shell-hello.nix hello -c hello | grep 'Hello World'
|
nix shell -f shell-hello.nix hello -c hello | grep 'Hello World'
|
||||||
nix shell -f shell-hello.nix hello -c hello NixOS | grep 'Hello NixOS'
|
nix shell -f shell-hello.nix hello -c hello NixOS | grep 'Hello NixOS'
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue