From a5f2ff6ce87b1a07953461536f2b0c22631c94ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Fri, 27 Feb 2026 20:27:00 +0100 Subject: [PATCH 1/2] pack-objects: remove duplicate --stdin-packs definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cd846bacc7 (pack-objects: introduce '--stdin-packs=follow', 2025-06-23) added a new definition of the option --stdin-packs that accepts an argument. It kept the old definition, which still shows up in the short help, but is shadowed by the new one. Remove it. Hinted-at-by: Junio C Hamano Signed-off-by: René Scharfe Signed-off-by: Junio C Hamano --- builtin/pack-objects.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index ff6900b654..8849cb1948 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -4925,8 +4925,6 @@ int cmd_pack_objects(int argc, OPT_CALLBACK_F(0, "stdin-packs", &stdin_packs, N_("mode"), N_("read packs from stdin"), PARSE_OPT_OPTARG, parse_stdin_packs_mode), - OPT_BOOL(0, "stdin-packs", &stdin_packs, - N_("read packs from stdin")), OPT_BOOL(0, "stdout", &pack_to_stdout, N_("output pack to stdout")), OPT_BOOL(0, "include-tag", &include_tag, From 237e520d81201eee609cf21e24f1c7ac6719ec8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 28 Feb 2026 10:19:16 +0100 Subject: [PATCH 2/2] parseopt: check for duplicate long names and numerical options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already check for duplicate short names. Check for and report duplicate long names and numerical options as well. Perform the slightly expensive string duplicate check only when showing the usage to keep the cost of normal invocations low. t0012-help.sh covers it. Helped-by: Jeff King Signed-off-by: René Scharfe Signed-off-by: Junio C Hamano --- parse-options.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/parse-options.c b/parse-options.c index 5224203ffe..6d9fc7bdc7 100644 --- a/parse-options.c +++ b/parse-options.c @@ -5,6 +5,7 @@ #include "gettext.h" #include "strbuf.h" #include "string-list.h" +#include "strmap.h" #include "utf8.h" static int disallow_abbreviated_options; @@ -634,6 +635,7 @@ static void check_typos(const char *arg, const struct option *options) static void parse_options_check(const struct option *opts) { char short_opts[128]; + bool saw_number_option = false; void *subcommand_value = NULL; memset(short_opts, '\0', sizeof(short_opts)); @@ -648,6 +650,11 @@ static void parse_options_check(const struct option *opts) else if (short_opts[opts->short_name]++) optbug(opts, "short name already used"); } + if (opts->type == OPTION_NUMBER) { + if (saw_number_option) + optbug(opts, "duplicate numerical option"); + saw_number_option = true; + } if (opts->flags & PARSE_OPT_NODASH && ((opts->flags & PARSE_OPT_OPTARG) || !(opts->flags & PARSE_OPT_NOARG) || @@ -707,6 +714,20 @@ static void parse_options_check(const struct option *opts) BUG_if_bug("invalid 'struct option'"); } +static void parse_options_check_harder(const struct option *opts) +{ + struct strset long_names = STRSET_INIT; + + for (; opts->type != OPTION_END; opts++) { + if (opts->long_name) { + if (!strset_add(&long_names, opts->long_name)) + optbug(opts, "long name already used"); + } + } + BUG_if_bug("invalid 'struct option'"); + strset_clear(&long_names); +} + static int has_subcommands(const struct option *options) { for (; options->type != OPTION_END; options++) @@ -1324,6 +1345,8 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t const char *prefix = usage_prefix; int saw_empty_line = 0; + parse_options_check_harder(opts); + if (!usagestr) return PARSE_OPT_HELP;