Commit 005bccea by Edward Thomson

cli: reorder arguments for subcommands

Instead of special casing `--help`, reorder the arguments for
subcommands so that it can handle "global" arguments like `--help`,
`-c key=value`, etc.
parent 1c381acf
...@@ -18,6 +18,10 @@ static char **args = NULL; ...@@ -18,6 +18,10 @@ static char **args = NULL;
const cli_opt_spec cli_common_opts[] = { const cli_opt_spec cli_common_opts[] = {
{ CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1, { CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
CLI_OPT_USAGE_DEFAULT, NULL, "display help information" }, CLI_OPT_USAGE_DEFAULT, NULL, "display help information" },
{ CLI_OPT_TYPE_VALUE, NULL, 'c', NULL, 0,
CLI_OPT_USAGE_DEFAULT, "key=value", "add configuration value" },
{ CLI_OPT_TYPE_VALUE, "config-env", 0, NULL, 0,
CLI_OPT_USAGE_DEFAULT, "key=value", "set configuration value to environment variable" },
{ CLI_OPT_TYPE_SWITCH, "version", 0, &show_version, 1, { CLI_OPT_TYPE_SWITCH, "version", 0, &show_version, 1,
CLI_OPT_USAGE_DEFAULT, NULL, "display the version" }, CLI_OPT_USAGE_DEFAULT, NULL, "display the version" },
{ CLI_OPT_TYPE_ARG, "command", 0, &command, 0, { CLI_OPT_TYPE_ARG, "command", 0, &command, 0,
...@@ -36,14 +40,33 @@ const cli_cmd_spec cli_cmds[] = { ...@@ -36,14 +40,33 @@ const cli_cmd_spec cli_cmds[] = {
{ NULL } { NULL }
}; };
/*
* Reorder the argv as it was given, since git has the notion of global
* options (like `--help` or `-c key=val`) that we want to pass to the
* subcommand, and that can appear early in the arguments, before the
* command name. Put the command-name in argv[1] to allow easier parsing.
*/
static void reorder_args(char **argv, size_t first)
{
char *tmp;
size_t i;
if (first == 1)
return;
tmp = argv[first];
for (i = first; i > 1; i--)
argv[i] = argv[i - 1];
argv[1] = tmp;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const cli_cmd_spec *cmd; const cli_cmd_spec *cmd;
cli_opt_parser optparser; cli_opt_parser optparser;
cli_opt opt; cli_opt opt;
char *help_args[3] = { NULL };
int help_args_len;
int args_len = 0;
int ret = 0; int ret = 0;
if (git_libgit2_init() < 0) { if (git_libgit2_init() < 0) {
...@@ -67,8 +90,7 @@ int main(int argc, char **argv) ...@@ -67,8 +90,7 @@ int main(int argc, char **argv)
* remaining arguments as args for the command itself. * remaining arguments as args for the command itself.
*/ */
if (command) { if (command) {
args = &argv[optparser.idx]; reorder_args(argv, optparser.idx);
args_len = (int)(argc - optparser.idx);
break; break;
} }
} }
...@@ -78,28 +100,13 @@ int main(int argc, char **argv) ...@@ -78,28 +100,13 @@ int main(int argc, char **argv)
goto done; goto done;
} }
/*
* If `--help <command>` is specified, delegate to that command's
* `--help` option. If no command is specified, run the `help`
* command. Do this by updating the args to emulate that behavior.
*/
if (!command || show_help) {
help_args[0] = command ? (char *)command : "help";
help_args[1] = command ? "--help" : NULL;
help_args_len = command ? 2 : 1;
command = help_args[0];
args = help_args;
args_len = help_args_len;
}
if ((cmd = cli_cmd_spec_byname(command)) == NULL) { if ((cmd = cli_cmd_spec_byname(command)) == NULL) {
ret = cli_error("'%s' is not a %s command. See '%s help'.", ret = cli_error("'%s' is not a %s command. See '%s help'.",
command, PROGRAM_NAME, PROGRAM_NAME); command, PROGRAM_NAME, PROGRAM_NAME);
goto done; goto done;
} }
ret = cmd->fn(args_len, args); ret = cmd->fn(argc - 1, &argv[1]);
done: done:
git_libgit2_shutdown(); git_libgit2_shutdown();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment