Merge branch 'rs/parse-options-duplicated-long-options' into next

The parse-options API learned to notice an options[] array with
duplicated long options.

* rs/parse-options-duplicated-long-options:
  parseopt: check for duplicate long names and numerical options
  pack-objects: remove duplicate --stdin-packs definition
This commit is contained in:
Junio C Hamano
2026-03-03 13:41:20 -08:00
2 changed files with 23 additions and 2 deletions

View File

@@ -4922,8 +4922,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,

View File

@@ -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;
@@ -641,6 +642,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));
@@ -655,6 +657,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) ||
@@ -714,6 +721,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++)
@@ -1339,6 +1360,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;