nix run: Allow passing a command to execute

E.g.

  nix run nixpkgs.hello -c hello --greeting Hallo

Note that unlike "nix-shell --command", no quoting of arguments is
necessary.

"-c" (short for "--command") cannot be combined with "--" because they
both consume all remaining arguments. But since installables shouldn't
start with a dash, this is unlikely to cause problems.
This commit is contained in:
Eelco Dolstra 2017-08-29 14:28:57 +02:00
parent 93a5ef0516
commit 5cc8609e30
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
3 changed files with 19 additions and 3 deletions

View file

@ -102,9 +102,11 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
++pos; ++pos;
Strings args; Strings args;
for (size_t n = 0 ; n < flag.arity; ++n) { for (size_t n = 0 ; n < flag.arity; ++n) {
if (pos == end) if (pos == end) {
if (flag.arity == ArityAny) break;
throw UsageError(format("flag '%1%' requires %2% argument(s)") throw UsageError(format("flag '%1%' requires %2% argument(s)")
% name % flag.arity); % name % flag.arity);
}
args.push_back(*pos++); args.push_back(*pos++);
} }
flag.handler(args); flag.handler(args);

View file

@ -26,6 +26,8 @@ public:
protected: protected:
static const size_t ArityAny = std::numeric_limits<size_t>::max();
/* Flags. */ /* Flags. */
struct Flag struct Flag
{ {

View file

@ -17,8 +17,20 @@ std::string chrootHelperName = "__run_in_chroot";
struct CmdRun : InstallablesCommand struct CmdRun : InstallablesCommand
{ {
Strings command = { "bash" };
CmdRun() CmdRun()
{ {
mkFlag()
.longName("command")
.shortName('c')
.description("command and arguments to be executed; defaults to 'bash'")
.arity(ArityAny)
.labels({"command", "args"})
.handler([&](Strings ss) {
if (ss.empty()) throw UsageError("--command requires at least one argument");
command = ss;
});
} }
std::string name() override std::string name() override
@ -43,8 +55,8 @@ struct CmdRun : InstallablesCommand
unixPath.push_front(path + "/bin"); unixPath.push_front(path + "/bin");
setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1); setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1);
std::string cmd = "bash"; std::string cmd = *command.begin();
Strings args = { cmd }; Strings args = command;
/* If this is a diverted store (i.e. its "logical" location /* If this is a diverted store (i.e. its "logical" location
(typically /nix/store) differs from its "physical" location (typically /nix/store) differs from its "physical" location