git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 00/20] parse-options: handle subcommands

From
SZEDER Gábor <szeder.dev@gmail.com>
Date
Aug 19, 2022, 16:03 UTC
Message-ID
<20220819160411.1791200-1-szeder.dev@gmail.com>
In-Reply-To
<20220725123857.2773963-1-szeder.dev@gmail.com>

Several Git commands have subcommands to implement mutually exclusive "operation modes", and they usually parse their subcommand argument with a bunch of if-else if statements.

Teach parse-options to handle subcommands as well, which will result in shorter and simpler code with consistent error handling and error messages on unknown or missing subcommand, and it will also make possible for our Bash completion script to handle subcommands programmatically in a follow-up series.

Changes since v1:
  - Commit message updates.
  - Put the troublesome subcommand arg between `' in error messages.
  - Use designated initializers for OPT_SUBCOMMAND.
  - Remove the unused 'kept_unknown' flag from 'struct parse_opt_ctx_t'
    (it was used in WIP version of this patch series, that I didn't manage
    to remove completely).
  - Drop cmd_worktree()'s NO_PARSEOPT flag in the right patch.
  - Use 'git -C ...' instead of ( cd ... && ... ) in t5505's new tests.
  - Update API doc and BUG() string to mention PARSE_OPT_KEEP_UNKNOWN_OPT.
  - Minor test helper refactorings.
SZEDER Gábor (20):
  git.c: update NO_PARSEOPT markings
  t3301-notes.sh: check that default operation mode doesn't take
    arguments
  t5505-remote.sh: check the behavior without a subcommand
  t0040-parse-options: test parse_options() with various
    'parse_opt_flags'
  api-parse-options.txt: fix description of OPT_CMDMODE
  parse-options: PARSE_OPT_KEEP_UNKNOWN only applies to --options
  parse-options: clarify the limitations of PARSE_OPT_NODASH
  parse-options: drop leading space from '--git-completion-helper'
    output
  parse-options: add support for parsing subcommands
  builtin/bundle.c: let parse-options parse subcommands
  builtin/commit-graph.c: let parse-options parse subcommands
  builtin/gc.c: let parse-options parse 'git maintenance's subcommands
  builtin/hook.c: let parse-options parse subcommands
  builtin/multi-pack-index.c: let parse-options parse subcommands
  builtin/notes.c: let parse-options parse subcommands
  builtin/reflog.c: let parse-options parse subcommands
  builtin/remote.c: let parse-options parse subcommands
  builtin/sparse-checkout.c: let parse-options parse subcommands
  builtin/stash.c: let parse-options parse subcommands
  builtin/worktree.c: let parse-options parse subcommands
 Documentation/technical/api-parse-options.txt |  49 +++-
 builtin/archive.c                             |   2 +-
 builtin/bisect--helper.c                      |   2 +-
 builtin/blame.c                               |   1 +
 builtin/bundle.c                              |  25 +-
 builtin/commit-graph.c                        |  30 +--
 builtin/difftool.c                            |   2 +-
 builtin/env--helper.c                         |   2 +-
 builtin/fast-export.c                         |   2 +-
 builtin/gc.c                                  |  42 +--
 builtin/hook.c                                |  12 +-
 builtin/log.c                                 |   4 +-
 builtin/multi-pack-index.c                    |  51 ++--
 builtin/notes.c                               |  43 ++-
 builtin/reflog.c                              |  43 +--
 builtin/remote.c                              |  70 +++--
 builtin/revert.c                              |   2 +-
 builtin/shortlog.c                            |   1 +
 builtin/sparse-checkout.c                     |  48 ++--
 builtin/stash.c                               |  59 ++--
 builtin/worktree.c                            |  31 +--
 diff.c                                        |   2 +-
 git.c                                         |  14 +-
 parse-options.c                               | 118 +++++++-
 parse-options.h                               |  29 +-
 t/helper/test-parse-options.c                 | 127 +++++++++
 t/helper/test-serve-v2.c                      |   2 +-
 t/helper/test-tool.c                          |   2 +
 t/helper/test-tool.h                          |   2 +
 t/t0040-parse-options.sh                      | 255 ++++++++++++++++++
 t/t3301-notes.sh                              |   5 +
 t/t3903-stash.sh                              |   2 +-
 t/t5318-commit-graph.sh                       |   4 +-
 t/t5505-remote.sh                             |  20 ++
 t/t7900-maintenance.sh                        |  10 +-
 35 files changed, 803 insertions(+), 310 deletions(-)
Range-diff:
 1:  78448310f9 !  1:  8128131f7b git.c: update NO_PARSEOPT markings
    @@ Commit message
         Update this list, and remove this flag from the commands that by now
         use parse-options.
     
    +    After this change we can TAB complete --options of the plumbing
    +    commands 'commit-tree', 'mailinfo' and 'mktag'.
    +
         Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
     
      ## git.c ##
    @@ git.c: static struct cmd_struct commands[] = {
      	{ "mktree", cmd_mktree, RUN_SETUP },
      	{ "multi-pack-index", cmd_multi_pack_index, RUN_SETUP },
      	{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
    -@@ git.c: static struct cmd_struct commands[] = {
    - 	{ "verify-tag", cmd_verify_tag, RUN_SETUP },
    - 	{ "version", cmd_version },
    - 	{ "whatchanged", cmd_whatchanged, RUN_SETUP },
    --	{ "worktree", cmd_worktree, RUN_SETUP | NO_PARSEOPT },
    -+	{ "worktree", cmd_worktree, RUN_SETUP },
    - 	{ "write-tree", cmd_write_tree, RUN_SETUP },
    - };
    - 
 2:  dee73c9832 =  2:  a8895169e7 t3301-notes.sh: check that default operation mode doesn't take arguments
 3:  4ce0c7717b !  3:  ecc7ca97e7 t5505-remote.sh: check the behavior without a subcommand
    @@ t/t5505-remote.sh: test_expect_success 'add invalid foreign_vcs remote' '
      '
      
     +test_expect_success 'without subcommand' '
    -+	(
    -+		cd test &&
    -+		git remote >actual &&
    -+		echo origin >expect &&
    -+		test_cmp expect actual
    -+	)
    ++	echo origin >expect &&
    ++	git -C test remote >actual &&
    ++	test_cmp expect actual
     +'
     +
     +test_expect_success 'without subcommand accepts -v' '
    -+	cat >test/expect <<-EOF &&
    ++	cat >expect <<-EOF &&
     +	origin	$(pwd)/one (fetch)
     +	origin	$(pwd)/one (push)
     +	EOF
    -+	(
    -+		cd test &&
    -+		git remote -v >actual &&
    -+		test_cmp expect actual
    -+	)
    ++	git -C test remote -v >actual &&
    ++	test_cmp expect actual
     +'
     +
     +test_expect_success 'without subcommand does not take arguments' '
    -+	(
    -+		cd test &&
    -+		test_expect_code 129 git remote origin 2>err &&
    -+		grep "^error: Unknown subcommand:" err
    -+	)
    ++	test_expect_code 129 git -C test remote origin 2>err &&
    ++	grep "^error: Unknown subcommand:" err
     +'
     +
      cat >test/expect <<EOF
 4:  7e7bf30b32 !  4:  84c1aa3318 t0040-parse-options: test parse_options() with various 'parse_opt_flags'
    @@ t/helper/test-parse-options.c: int cmd__parse_options(int argc, const char **arg
      	return ret;
      }
     +
    ++static void print_args(int argc, const char **argv)
    ++{
    ++	for (int i = 0; i < argc; i++)
    ++		printf("arg %02d: %s\n", i, argv[i]);
    ++}
    ++
     +static int parse_options_flags__cmd(int argc, const char **argv,
     +				    enum parse_opt_flags test_flags)
     +{
    @@ t/helper/test-parse-options.c: int cmd__parse_options(int argc, const char **arg
     +	argc = parse_options(argc, argv, NULL, options, usage, test_flags);
     +
     +	printf("opt: %d\n", opt);
    -+	for (int i = 0; i < argc; i++)
    -+		printf("arg %02d: %s\n", i, argv[i]);
    ++	print_args(argc, argv);
     +
     +	return 0;
     +}
    @@ t/t0040-parse-options.sh: test_expect_success '--end-of-options treats remainder
     +test_expect_success 'NO_INTERNAL_HELP works for -h' '
     +	test_expect_code 129 test-tool parse-options-flags --no-internal-help cmd -h 2>err &&
     +	cat err &&
    -+	grep "^error: unknown switch \`h'\''" err &&
    ++	grep "^error: unknown switch \`h$SQ" err &&
     +	grep "^usage: " err
     +'
     +
 5:  8515609ac2 =  5:  40b51c9992 api-parse-options.txt: fix description of OPT_CMDMODE
 6:  60885e91cf =  6:  7f561992a5 parse-options: PARSE_OPT_KEEP_UNKNOWN only applies to --options
 7:  2e1d40b4f0 =  7:  27a66b0fcd parse-options: clarify the limitations of PARSE_OPT_NODASH
 8:  2e4f9259ba =  8:  722a47874a parse-options: drop leading space from '--git-completion-helper' output
 9:  caf0a395df !  9:  b65385a02d parse-options: add support for parsing subcommands
    @@ Commit message
             return fn(argc, argv, prefix);
     
         Here each OPT_SUBCOMMAND specifies the name of the subcommand and the
    -    function implementing it, and the same pointer to 'fn' where
    -    parse_options() will store the function associated with the given
    -    subcommand.  There is no need to check whether 'fn' is non-NULL before
    -    invoking it: if there were no subcommands given on the command line
    -    then the parse_options() call would error out and show usage.  In case
    -    a command has a default operation mode, 'fn' should be initialized to
    -    the function implementing that mode, and parse_options() should be
    -    invoked with the PARSE_OPT_SUBCOMMAND_OPTIONAL flag.
    +    function implementing it, and the address of the same 'fn' subcommand
    +    function pointer.  parse_options() then processes the arguments until
    +    it finds the first argument matching one of the subcommands, sets 'fn'
    +    to the function associated with that subcommand, and returns, leaving
    +    the rest of the arguments unprocessed.  If none of the listed
    +    subcommands is found among the arguments, parse_options() will show
    +    usage and abort.
    +
    +    If a command has a default operation mode, 'fn' should be initialized
    +    to the function implementing that mode, and parse_options() should be
    +    invoked with the PARSE_OPT_SUBCOMMAND_OPTIONAL flag.  In this case
    +    parse_options() won't error out when not finding any subcommands, but
    +    will return leaving 'fn' unchanged.  Note that if that default
    +    operation mode has any --options, then the PARSE_OPT_KEEP_UNKNOWN_OPT
    +    flag is necessary as well (otherwise parse_options() would error out
    +    upon seeing the unknown option meant to the default operation mode).
     
         Some thoughts about the implementation:
     
    -      - Arguably it is a bit weird that the same pointer to 'fn' have to
    -        be specified as 'value' for each OPT_SUBCOMMAND, but we need a way
    -        to tell parse_options() where to put the function associated with
    -        the given subcommand, and I didn't like the alternatives:
    +      - The same pointer to 'fn' must be specified as 'value' for each
    +        OPT_SUBCOMMAND, because there can be only one set of mutually
    +        exclusive subcommands; parse_options() will BUG() otherwise.
    +
    +        There are other ways to tell parse_options() where to put the
    +        function associated with the subcommand given on the command line,
    +        but I didn't like them:
     
               - Change parse_options()'s signature by adding a pointer to
                 subcommand function to be set to the function associated with
    @@ Documentation/technical/api-parse-options.txt: Flags are the bitwise-or of:
     +	Don't error out when no subcommand is specified.
     +
     +Note that `PARSE_OPT_STOP_AT_NON_OPTION` is incompatible with subcommands;
    -+while `PARSE_OPT_KEEP_DASHDASH` and `PARSE_OPT_KEEP_UNKNOWN` can only be
    ++while `PARSE_OPT_KEEP_DASHDASH` and `PARSE_OPT_KEEP_UNKNOWN_OPT` can only be
     +used with subcommands when combined with `PARSE_OPT_SUBCOMMAND_OPTIONAL`.
     +
      Data Structure
    @@ parse-options.c: static void parse_options_start_1(struct parse_opt_ctx_t *ctx,
     +			BUG("subcommands are incompatible with PARSE_OPT_STOP_AT_NON_OPTION");
     +		if (!(flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)) {
     +			if (flags & PARSE_OPT_KEEP_UNKNOWN_OPT)
    -+				BUG("subcommands are incompatible with PARSE_OPT_KEEP_UNKNOWN unless in combination with PARSE_OPT_SUBCOMMAND_OPTIONAL");
    ++				BUG("subcommands are incompatible with PARSE_OPT_KEEP_UNKNOWN_OPT unless in combination with PARSE_OPT_SUBCOMMAND_OPTIONAL");
     +			if (flags & PARSE_OPT_KEEP_DASHDASH)
     +				BUG("subcommands are incompatible with PARSE_OPT_KEEP_DASHDASH unless in combination with PARSE_OPT_SUBCOMMAND_OPTIONAL");
     +		}
    @@ parse-options.c: enum parse_opt_result parse_options_step(struct parse_opt_ctx_t
     +					 * So we are done parsing.
     +					 */
     +					return PARSE_OPT_DONE;
    -+				error(_("unknown subcommand: %s"), arg);
    ++				error(_("unknown subcommand: `%s'"), arg);
     +				usage_with_options(usagestr, options);
     +			case PARSE_OPT_COMPLETE:
     +			case PARSE_OPT_HELP:
     +			case PARSE_OPT_ERROR:
     +			case PARSE_OPT_DONE:
     +			case PARSE_OPT_NON_OPTION:
    ++				/* Impossible. */
     +				BUG("parse_subcommand() cannot return these");
     +			}
      		}
    @@ parse-options.c: enum parse_opt_result parse_options_step(struct parse_opt_ctx_t
     +		}
      		if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN_OPT))
      			return PARSE_OPT_UNKNOWN;
    -+		ctx->kept_unknown = 1;
      		ctx->out[ctx->cpidx++] = ctx->argv[0];
    - 		ctx->opt = NULL;
    - 	}
     @@ parse-options.c: int parse_options(int argc, const char **argv,
      	case PARSE_OPT_COMPLETE:
      		exit(0);
    @@ parse-options.h: struct option {
      #define OPT_ALIAS(s, l, source_long_name) \
      	{ OPTION_ALIAS, (s), (l), (source_long_name) }
      
    -+#define OPT_SUBCOMMAND(l, v, fn)      { OPTION_SUBCOMMAND, 0, (l), (v), NULL, \
    -+					NULL, 0, NULL, 0, NULL, 0, (fn) }
    -+#define OPT_SUBCOMMAND_F(l, v, fn, f) { OPTION_SUBCOMMAND, 0, (l), (v), NULL, \
    -+					NULL, (f), NULL, 0, NULL, 0, (fn) }
    ++#define OPT_SUBCOMMAND_F(l, v, fn, f) { \
    ++	.type = OPTION_SUBCOMMAND, \
    ++	.long_name = (l), \
    ++	.value = (v), \
    ++	.flags = (f), \
    ++	.subcommand_fn = (fn) }
    ++#define OPT_SUBCOMMAND(l, v, fn)    OPT_SUBCOMMAND_F((l), (v), (fn), 0)
     +
      /*
       * parse_options() will filter out the processed options and leave the
    @@ parse-options.h: struct parse_opt_ctx_t {
      	int argc, cpidx, total;
      	const char *opt;
      	enum parse_opt_flags flags;
    -+	unsigned has_subcommands:1,
    -+		 kept_unknown:1;
    ++	unsigned has_subcommands;
      	const char *prefix;
      	const char **alias_groups; /* must be in groups of 3 elements! */
      	struct option *updated_options;
    @@ t/helper/test-parse-options.c: int cmd__parse_options_flags(int argc, const char
      	return parse_options_flags__cmd(argc, argv, test_flags);
      }
     +
    -+static void print_subcommand_args(const char *fn_name, int argc,
    -+				  const char **argv)
    -+{
    -+	int i;
    -+	printf("fn: %s\n", fn_name);
    -+	for (i = 0; i < argc; i++)
    -+		printf("arg %02d: %s\n", i, argv[i]);
    -+}
    -+
     +static int subcmd_one(int argc, const char **argv, const char *prefix)
     +{
    -+	print_subcommand_args("subcmd_one", argc, argv);
    ++	printf("fn: subcmd_one\n");
    ++	print_args(argc, argv);
     +	return 0;
     +}
     +
     +static int subcmd_two(int argc, const char **argv, const char *prefix)
     +{
    -+	print_subcommand_args("subcmd_two", argc, argv);
    ++	printf("fn: subcmd_two\n");
    ++	print_args(argc, argv);
     +	return 0;
     +}
     +
    @@ t/t0040-parse-options.sh: test_expect_success 'KEEP_UNKNOWN_OPT | NO_INTERNAL_HE
     +
     +test_expect_success 'subcommand - unknown subcommand shows error and usage' '
     +	test_expect_code 129 test-tool parse-subcommand cmd nope 2>err &&
    -+	grep "^error: unknown subcommand: nope" err &&
    ++	grep "^error: unknown subcommand: \`nope$SQ" err &&
     +	grep ^usage: err
     +'
     +
     +test_expect_success 'subcommand - subcommands cannot be abbreviated' '
     +	test_expect_code 129 test-tool parse-subcommand cmd subcmd-o 2>err &&
    -+	grep "^error: unknown subcommand: subcmd-o$" err &&
    ++	grep "^error: unknown subcommand: \`subcmd-o$SQ$" err &&
     +	grep ^usage: err
     +'
     +
     +test_expect_success 'subcommand - no negated subcommands' '
     +	test_expect_code 129 test-tool parse-subcommand cmd no-subcmd-one 2>err &&
    -+	grep "^error: unknown subcommand: no-subcmd-one" err &&
    ++	grep "^error: unknown subcommand: \`no-subcmd-one$SQ" err &&
     +	grep ^usage: err
     +'
     +
10:  cac17fa063 = 10:  3526a93d90 builtin/bundle.c: let parse-options parse subcommands
11:  9cfd5875fb ! 11:  a9533e14a5 builtin/commit-graph.c: let parse-options parse subcommands
    @@ t/t5318-commit-graph.sh: test_expect_success 'usage' '
      test_expect_success 'usage shown with an error on unknown sub-command' '
      	cat >expect <<-\EOF &&
     -	error: unrecognized subcommand: unknown
    -+	error: unknown subcommand: unknown
    ++	error: unknown subcommand: `unknown'\''
      	EOF
      	test_expect_code 129 git commit-graph unknown 2>stderr &&
      	grep error stderr >actual &&
12:  cab2adf79b ! 12:  501a2bd1b5 builtin/gc.c: let parse-options parse 'git maintenance's subcommands
    @@ t/t7900-maintenance.sh: test_systemd_analyze_verify () {
     +	test_expect_code 129 git maintenance -h >actual &&
     +	test_i18ngrep "usage: git maintenance <subcommand>" actual &&
     +	test_expect_code 129 git maintenance barf 2>err &&
    -+	test_i18ngrep "unknown subcommand: barf" err &&
    ++	test_i18ngrep "unknown subcommand: \`barf'\''" err &&
     +	test_i18ngrep "usage: git maintenance" err &&
      	test_expect_code 129 git maintenance 2>err &&
     +	test_i18ngrep "error: need a subcommand" err &&
13:  6a16515cd8 ! 13:  a38a61756b builtin/hook.c: let parse-option parse subcommands
    @@ Metadata
     Author: SZEDER Gábor <szeder.dev@gmail.com>
     
      ## Commit message ##
    -    builtin/hook.c: let parse-option parse subcommands
    +    builtin/hook.c: let parse-options parse subcommands
     
         'git hook' parses its currently only subcommand with an if statement.
         parse-options has just learned to parse subcommands, so let's use that
14:  a5a7f28ced = 14:  f511717008 builtin/multi-pack-index.c: let parse-options parse subcommands
15:  0104f48ae1 = 15:  220bbf16cf builtin/notes.c: let parse-options parse subcommands
16:  250e12ddfc = 16:  d0e7329f42 builtin/reflog.c: let parse-options parse subcommands
17:  90a2968469 ! 17:  9af71fd655 builtin/remote.c: let parse-options parse subcommands
    @@ builtin/remote.c: static int set_url(int argc, const char **argv)
      }
     
      ## t/t5505-remote.sh ##
    -@@ t/t5505-remote.sh: test_expect_success 'without subcommand does not take arguments' '
    - 	(
    - 		cd test &&
    - 		test_expect_code 129 git remote origin 2>err &&
    --		grep "^error: Unknown subcommand:" err
    -+		grep "^error: unknown subcommand:" err
    - 	)
    +@@ t/t5505-remote.sh: test_expect_success 'without subcommand accepts -v' '
    + 
    + test_expect_success 'without subcommand does not take arguments' '
    + 	test_expect_code 129 git -C test remote origin 2>err &&
    +-	grep "^error: Unknown subcommand:" err
    ++	grep "^error: unknown subcommand:" err
      '
      
    + cat >test/expect <<EOF
18:  dc5c071b51 = 18:  2bd2d40bb3 builtin/sparse-checkout.c: let parse-options parse subcommands
19:  5c7cd8cbed = 19:  e8b7fdd2d8 builtin/stash.c: let parse-options parse subcommands
20:  4d884dfe62 ! 20:  6d8108292f builtin/worktree.c: let parse-options parse subcommands
    @@ builtin/worktree.c: static int repair(int ac, const char **av, const char *prefi
     +	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
     +	return fn(ac, av, prefix);
      }
    +
    + ## git.c ##
    +@@ git.c: static struct cmd_struct commands[] = {
    + 	{ "verify-tag", cmd_verify_tag, RUN_SETUP },
    + 	{ "version", cmd_version },
    + 	{ "whatchanged", cmd_whatchanged, RUN_SETUP },
    +-	{ "worktree", cmd_worktree, RUN_SETUP | NO_PARSEOPT },
    ++	{ "worktree", cmd_worktree, RUN_SETUP },
    + 	{ "write-tree", cmd_write_tree, RUN_SETUP },
    + };
    + 
-- 
2.37.2.817.g36f84ce71d
Previous: Ævar Arnfjörð BjarmasonNext: SZEDER Gábor
Message 49 of 97 in “parse-options: handle subcommands”
  1. 00/20 parse-options: handle subcommandsSZEDER Gábor, Jul 25, 2022
  2. 01/20 git.c: update NO_PARSEOPT markingsSZEDER Gábor, Jul 25, 2022
  3. Ævar Arnfjörð BjarmasonJul 25, 2022
  4. SZEDER GáborAug 2, 2022
  5. Junio C HamanoAug 2, 2022
  6. Ævar Arnfjörð BjarmasonAug 3, 2022
  7. SZEDER GáborAug 3, 2022
  8. Ævar Arnfjörð BjarmasonAug 4, 2022
  9. Junio C HamanoAug 11, 2022
  10. SZEDER GáborAug 12, 2022
  11. Junio C HamanoAug 12, 2022
  12. SZEDER GáborJul 26, 2022
  13. 02/20 t3301-notes.sh: check that default operation mode doesn't take argumentsSZEDER Gábor, Jul 25, 2022
  14. 03/20 t5505-remote.sh: check the behavior without a subcommandSZEDER Gábor, Jul 25, 2022
  15. Ævar Arnfjörð BjarmasonJul 25, 2022
  16. 04/20 t0040-parse-options: test parse_options() with various 'parse_opt_flags'SZEDER Gábor, Jul 25, 2022
  17. Ævar Arnfjörð BjarmasonJul 25, 2022
  18. SZEDER GáborAug 12, 2022
  19. 05/20 api-parse-options.txt: fix description of OPT_CMDMODESZEDER Gábor, Jul 25, 2022
  20. 06/20 parse-options: PARSE_OPT_KEEP_UNKNOWN only applies to --optionsSZEDER Gábor, Jul 25, 2022
  21. 07/20 parse-options: clarify the limitations of PARSE_OPT_NODASHSZEDER Gábor, Jul 25, 2022
  22. 08/20 parse-options: drop leading space from '--git-completion-helper' outputSZEDER Gábor, Jul 25, 2022
  23. 10/20 builtin/bundle.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  24. 09/20 parse-options: add support for parsing subcommandsSZEDER Gábor, Jul 25, 2022
  25. Ævar Arnfjörð BjarmasonJul 25, 2022
  26. SZEDER GáborJul 25, 2022
  27. Ævar Arnfjörð BjarmasonJul 25, 2022
  28. SZEDER GáborJul 25, 2022
  29. SZEDER GáborAug 12, 2022
  30. Junio C HamanoJul 25, 2022
  31. 11/20 builtin/commit-graph.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  32. 12/20 builtin/gc.c: let parse-options parse 'git maintenance's subcommandsSZEDER Gábor, Jul 25, 2022
  33. 13/20 builtin/hook.c: let parse-option parse subcommandsSZEDER Gábor, Jul 25, 2022
  34. 15/20 builtin/notes.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  35. Junio C HamanoJul 25, 2022
  36. 14/20 builtin/multi-pack-index.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  37. 16/20 builtin/reflog.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  38. 17/20 builtin/remote.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  39. 18/20 builtin/sparse-checkout.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  40. 19/20 builtin/stash.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  41. 20/20 builtin/worktree.c: let parse-options parse subcommandsSZEDER Gábor, Jul 25, 2022
  42. Derrick StoleeJul 25, 2022
  43. SZEDER GáborJul 25, 2022
  44. Derrick StoleeJul 25, 2022
  45. Ævar Arnfjörð BjarmasonJul 25, 2022
  46. Junio C HamanoJul 25, 2022
  47. Johannes SchindelinJul 26, 2022
  48. Ævar Arnfjörð BjarmasonJul 26, 2022
  49. 00/20 parse-options: handle subcommandsSZEDER Gábor, Aug 19, 2022
  50. 09/20 parse-options: add support for parsing subcommandsSZEDER Gábor, Aug 19, 2022
  51. Ævar Arnfjörð BjarmasonAug 19, 2022
  52. Ævar Arnfjörð BjarmasonAug 19, 2022
  53. 15/20 builtin/notes.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  54. Ævar Arnfjörð BjarmasonAug 19, 2022
  55. SZEDER GáborAug 21, 2022
  56. 17/20 builtin/remote.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  57. 02/20 t3301-notes.sh: check that default operation mode doesn't take argumentsSZEDER Gábor, Aug 19, 2022
  58. 13/20 builtin/hook.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  59. 10/20 builtin/bundle.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  60. Ævar Arnfjörð BjarmasonAug 19, 2022
  61. 12/20 builtin/gc.c: let parse-options parse 'git maintenance's subcommandsSZEDER Gábor, Aug 19, 2022
  62. Junio C HamanoAug 19, 2022
  63. 16/20 builtin/reflog.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  64. Ævar Arnfjörð BjarmasonAug 19, 2022
  65. 11/20 builtin/commit-graph.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  66. Ævar Arnfjörð BjarmasonAug 19, 2022
  67. Ævar Arnfjörð BjarmasonAug 19, 2022
  68. SZEDER GáborAug 19, 2022
  69. 18/20 builtin/sparse-checkout.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  70. 01/20 git.c: update NO_PARSEOPT markingsSZEDER Gábor, Aug 19, 2022
  71. 14/20 builtin/multi-pack-index.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  72. Ævar Arnfjörð BjarmasonAug 19, 2022
  73. 04/20 t0040-parse-options: test parse_options() with various 'parse_opt_flags'SZEDER Gábor, Aug 19, 2022
  74. Ævar Arnfjörð BjarmasonAug 19, 2022
  75. SZEDER GáborAug 20, 2022
  76. Junio C HamanoAug 19, 2022
  77. SZEDER GáborAug 20, 2022
  78. Junio C HamanoAug 20, 2022
  79. 08/20 parse-options: drop leading space from '--git-completion-helper' outputSZEDER Gábor, Aug 19, 2022
  80. Ævar Arnfjörð BjarmasonAug 19, 2022
  81. SZEDER GáborAug 19, 2022
  82. 19/20 builtin/stash.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  83. Ævar Arnfjörð BjarmasonAug 19, 2022
  84. SZEDER GáborAug 20, 2022
  85. 06/20 parse-options: PARSE_OPT_KEEP_UNKNOWN only applies to --optionsSZEDER Gábor, Aug 19, 2022
  86. 05/20 api-parse-options.txt: fix description of OPT_CMDMODESZEDER Gábor, Aug 19, 2022
  87. 20/20 builtin/worktree.c: let parse-options parse subcommandsSZEDER Gábor, Aug 19, 2022
  88. 07/20 parse-options: clarify the limitations of PARSE_OPT_NODASHSZEDER Gábor, Aug 19, 2022
  89. 03/20 t5505-remote.sh: check the behavior without a subcommandSZEDER Gábor, Aug 19, 2022
  90. 0/5 parse-options: minor cleanups for handling subcommandsSZEDER Gábor, Sep 5, 2022
  91. 2/5 test-parse-options.c: don't use for loop initial declarationSZEDER Gábor, Sep 5, 2022
  92. 1/5 t0040-parse-options: remove leftover debuggingSZEDER Gábor, Sep 5, 2022
  93. 3/5 test-parse-options.c: fix style of comparison with zeroSZEDER Gábor, Sep 5, 2022
  94. 4/5 notes: simplify default operation mode arguments checkSZEDER Gábor, Sep 5, 2022
  95. 5/5 notes, remote: show unknown subcommands between `'SZEDER Gábor, Sep 5, 2022
  96. Junio C HamanoSep 7, 2022
  97. SZEDER GáborSep 7, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.