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 [1]. Patches 1-8 are a mix of preparatory cleanups, documentation updates, and test coverage improvements. Patch 9 is the most important one, which teaches parse-options to handle subcommands. The remaining 10-20 convert most builtin commands with subcommands one by one to use parse-options to handle their subcommand parameters. This patch series has two conflicts with 'seen' (but none with 'next'): - builtin/bisect.c: after the conversion/rename from 'bisect--helper', cmd_bisect() doesn't use parse-options anymore. Take what's on 'seen' to resolve the conflict. Note that the conflicting topic should have marked cmd_bisect() with the NO_PARSEOPT flag in 'git.c's command list. - builtin/stash.c: add OPT_SUBCOMMAND entries for the two new subcommands 'export' and 'import' to resolve the conflict. [1] WIP with some one-liner commit messages and missing sign-offs here and there: https://github.com/szeder/git completion-subcommands 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-option 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 | 27 +- t/helper/test-parse-options.c | 129 +++++++++ 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 | 29 ++ t/t7900-maintenance.sh | 10 +- 35 files changed, 812 insertions(+), 310 deletions(-) -- 2.37.1.633.g6a0fa73e39