builtin/remote.c: let parse-options parse subcommands

'git remote' parses its subcommands with a long list of if-else if statements. parse-options has just learned to parse subcommands, so let's use that facility instead, with the benefits of shorter code, handling unknown subcommands, and listing subcommands for Bash completion. Make sure that the default operation mode doesn't accept any arguments; and while at it remove the capitalization of the error message and adjust the test checking it accordingly. Note that 'git remote' has both 'remove' and 'rm' subcommands, and the former is preferred [1], so hide the latter for completion. Note also that the functions implementing each subcommand only accept the 'argc' and '**argv' parameters, so add a (unused) '*prefix' parameter to make them match the type expected by parse-options, and thus avoid casting a bunch of function pointers. [1] e17dba8fe1 (remote: prefer subcommand name 'remove' to 'rm', 2012-09-06) Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

SZEDER Gábor committed Aug 19, 2022 at 18:04 UTC b26a412f1e96e40c419001991486cced837679a6
2 files changed +32 -40
builtin/remote.c
+31 -39
@@ -150,7 +150,7 @@ static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
150 return 0;
151 }
152
153 -static int add(int argc, const char **argv)
153 +static int add(int argc, const char **argv, const char *prefix)
154 {
155 int fetch = 0, fetch_tags = TAGS_DEFAULT;
156 unsigned mirror = MIRROR_NONE;
@@ -680,7 +680,7 @@ static void handle_push_default(const char* old_name, const char* new_name)
680 }
681
682
683 -static int mv(int argc, const char **argv)
683 +static int mv(int argc, const char **argv, const char *prefix)
684 {
685 int show_progress = isatty(2);
686 struct option options[] = {
@@ -844,7 +844,7 @@ static int mv(int argc, const char **argv)
844 return 0;
845 }
846
847 -static int rm(int argc, const char **argv)
847 +static int rm(int argc, const char **argv, const char *prefix)
848 {
849 struct option options[] = {
850 OPT_END()
@@ -1255,7 +1255,7 @@ static int show_all(void)
1255 return result;
1256 }
1257
1258 -static int show(int argc, const char **argv)
1258 +static int show(int argc, const char **argv, const char *prefix)
1259 {
1260 int no_query = 0, result = 0, query_flag = 0;
1261 struct option options[] = {
@@ -1358,7 +1358,7 @@ static int show(int argc, const char **argv)
1358 return result;
1359 }
1360
1361 -static int set_head(int argc, const char **argv)
1361 +static int set_head(int argc, const char **argv, const char *prefix)
1362 {
1363 int i, opt_a = 0, opt_d = 0, result = 0;
1364 struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
@@ -1463,7 +1463,7 @@ static int prune_remote(const char *remote, int dry_run)
1463 return result;
1464 }
1465
1466 -static int prune(int argc, const char **argv)
1466 +static int prune(int argc, const char **argv, const char *prefix)
1467 {
1468 int dry_run = 0, result = 0;
1469 struct option options[] = {
@@ -1492,7 +1492,7 @@ static int get_remote_default(const char *key, const char *value, void *priv)
1492 return 0;
1493 }
1494
1495 -static int update(int argc, const char **argv)
1495 +static int update(int argc, const char **argv, const char *prefix)
1496 {
1497 int i, prune = -1;
1498 struct option options[] = {
@@ -1575,7 +1575,7 @@ static int set_remote_branches(const char *remotename, const char **branches,
1575 return 0;
1576 }
1577
1578 -static int set_branches(int argc, const char **argv)
1578 +static int set_branches(int argc, const char **argv, const char *prefix)
1579 {
1580 int add_mode = 0;
1581 struct option options[] = {
@@ -1594,7 +1594,7 @@ static int set_branches(int argc, const char **argv)
1594 return set_remote_branches(argv[0], argv + 1, add_mode);
1595 }
1596
1597 -static int get_url(int argc, const char **argv)
1597 +static int get_url(int argc, const char **argv, const char *prefix)
1598 {
1599 int i, push_mode = 0, all_mode = 0;
1600 const char *remotename = NULL;
@@ -1647,7 +1647,7 @@ static int get_url(int argc, const char **argv)
1647 return 0;
1648 }
1649
1650 -static int set_url(int argc, const char **argv)
1650 +static int set_url(int argc, const char **argv, const char *prefix)
1651 {
1652 int i, push_mode = 0, add_mode = 0, delete_mode = 0;
1653 int matches = 0, negative_matches = 0;
@@ -1739,41 +1739,33 @@ out:
1739
1740 int cmd_remote(int argc, const char **argv, const char *prefix)
1741 {
1742 + parse_opt_subcommand_fn *fn = NULL;
1743 struct option options[] = {
1744 OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")),
1745 + OPT_SUBCOMMAND("add", &fn, add),
1746 + OPT_SUBCOMMAND("rename", &fn, mv),
1747 + OPT_SUBCOMMAND_F("rm", &fn, rm, PARSE_OPT_NOCOMPLETE),
1748 + OPT_SUBCOMMAND("remove", &fn, rm),
1749 + OPT_SUBCOMMAND("set-head", &fn, set_head),
1750 + OPT_SUBCOMMAND("set-branches", &fn, set_branches),
1751 + OPT_SUBCOMMAND("get-url", &fn, get_url),
1752 + OPT_SUBCOMMAND("set-url", &fn, set_url),
1753 + OPT_SUBCOMMAND("show", &fn, show),
1754 + OPT_SUBCOMMAND("prune", &fn, prune),
1755 + OPT_SUBCOMMAND("update", &fn, update),
1756 OPT_END()
1757 };
1746 - int result;
1758
1759 argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
1749 - PARSE_OPT_STOP_AT_NON_OPTION);
1760 + PARSE_OPT_SUBCOMMAND_OPTIONAL);
1761
1751 - if (argc < 1)
1752 - result = show_all();
1753 - else if (!strcmp(argv[0], "add"))
1754 - result = add(argc, argv);
1755 - else if (!strcmp(argv[0], "rename"))
1756 - result = mv(argc, argv);
1757 - else if (!strcmp(argv[0], "rm") || !strcmp(argv[0], "remove"))
1758 - result = rm(argc, argv);
1759 - else if (!strcmp(argv[0], "set-head"))
1760 - result = set_head(argc, argv);
1761 - else if (!strcmp(argv[0], "set-branches"))
1762 - result = set_branches(argc, argv);
1763 - else if (!strcmp(argv[0], "get-url"))
1764 - result = get_url(argc, argv);
1765 - else if (!strcmp(argv[0], "set-url"))
1766 - result = set_url(argc, argv);
1767 - else if (!strcmp(argv[0], "show"))
1768 - result = show(argc, argv);
1769 - else if (!strcmp(argv[0], "prune"))
1770 - result = prune(argc, argv);
1771 - else if (!strcmp(argv[0], "update"))
1772 - result = update(argc, argv);
1773 - else {
1774 - error(_("Unknown subcommand: %s"), argv[0]);
1775 - usage_with_options(builtin_remote_usage, options);
1762 + if (fn) {
1763 + return !!fn(argc, argv, prefix);
1764 + } else {
1765 + if (argc) {
1766 + error(_("unknown subcommand: %s"), argv[0]);
1767 + usage_with_options(builtin_remote_usage, options);
1768 + }
1769 + return !!show_all();
1770 }
1777 -
1778 - return result ? 1 : 0;
1771 }
t/t5505-remote.sh
+1 -1
@@ -258,7 +258,7 @@ test_expect_success 'without subcommand accepts -v' '
258
259 test_expect_success 'without subcommand does not take arguments' '
260 test_expect_code 129 git -C test remote origin 2>err &&
261 - grep "^error: Unknown subcommand:" err
261 + grep "^error: unknown subcommand:" err
262 '
263
264 cat >test/expect <<EOF