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

[PATCH v2 2/2] parseopt: check for duplicate long names and numerical options

From
René Scharfe <l.s.r@web.de>
Date
Feb 28, 2026, 09:19 UTC
Message-ID
<6b674316-9a6e-4f57-b32c-f1824869ba7e@web.de>
In-Reply-To
<7693799a-91a2-480a-ae3e-29f8eed5b55a@web.de>

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 <peff@peff.net>
Signed-off-by: René Scharfe <l.s.r@web.de>
---
Changes since v1:
- Removed strset_contains() call.
- Only check for duplicate long names when showing the usage.
 parse-options.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
diff --git a/parse-options.c b/parse-options.c
index c9cafc21b9..0214c106d4 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;
@@ -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,19 @@ 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 +1359,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;
 
-- 
2.53.0
Previous: René ScharfeNext: Jeff King
Message 7 of 12 in “[Bug] duplicated long-form options go unnoticed”
  1. Junio C HamanoFeb 27, 2026
  2. 2/2 parseopt: check for duplicate long names and numerical optionsRené Scharfe, Feb 27, 2026
  3. Jeff KingFeb 27, 2026
  4. Jeff KingFeb 27, 2026
  5. Junio C HamanoFeb 27, 2026
  6. René ScharfeFeb 28, 2026
  7. 2/2 parseopt: check for duplicate long names and numerical optionsRené Scharfe, Feb 28, 2026
  8. Jeff KingFeb 28, 2026
  9. René ScharfeFeb 28, 2026
  10. Jeff KingMar 2, 2026
  11. Junio C HamanoMar 1, 2026
  12. 1/2 pack-objects: remove duplicate --stdin-packs definitionRené Scharfe, Feb 27, 2026

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.