From: Jeff King <peff@peff.net>
To: "René Scharfe" <l.s.r@web.de>
Cc: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Subject: Re: [PATCH v2 2/2] parseopt: check for duplicate long names and numerical options
Date: Sat, 28 Feb 2026 05:58:49 -0500 [thread overview]
Message-ID: <20260228105849.GA3626520@coredump.intra.peff.net> (raw)
In-Reply-To: <6b674316-9a6e-4f57-b32c-f1824869ba7e@web.de>
On Sat, Feb 28, 2026 at 10:19:16AM +0100, René Scharfe wrote:
> 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.
Nice, this seems like the perfect compromise to me. We get a runtime
switch that kicks in at the moment we want, and we don't even have to
pollute the world with a new switch or environment variable.
> +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);
> +}
I confirmed on my silly pathological case that invoking rev-parse with a
real option shows no slowdown, and we now pay the same 10ms cost to show
"-h".
Your other email made me wonder how the sorted-array solution might
perform (patch below). It shaves off 2ms of those 10. Probably not worth
caring about for "-h" output (which is already spending another 5-10ms
to generate the output, versus a normal parse).
-Peff
-- >8 --
diff --git a/parse-options.c b/parse-options.c
index 0214c106d4..1ea7efd5a3 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -721,17 +721,39 @@ static void parse_options_check(const struct option *opts)
BUG_if_bug("invalid 'struct option'");
}
+static int qsort_strcmp(const void *va, const void *vb)
+{
+ const char *a = *(const char **)va;
+ const char *b = *(const char **)vb;
+ return strcmp(a, b);
+}
+
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");
- }
+ const struct option *p;
+ const char **long_names;
+ size_t i, len;
+
+ len = 0;
+ for (p = opts; p->type != OPTION_END; p++) {
+ if (p->long_name)
+ len++;
}
- BUG_if_bug("invalid 'struct option'");
- strset_clear(&long_names);
+
+ ALLOC_ARRAY(long_names, len);
+ i = 0;
+ for (p = opts; p->type != OPTION_END; p++) {
+ if (p->long_name)
+ long_names[i++] = p->long_name;
+ }
+
+ QSORT(long_names, len, qsort_strcmp);
+ for (i = 1; i < len; i++) {
+ if (!strcmp(long_names[i], long_names[i-1]))
+ BUG("long name %s used twice", long_names[i]);
+ }
+
+ free(long_names);
}
static int has_subcommands(const struct option *options)
next prev parent reply other threads:[~2026-02-28 10:58 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-27 0:13 [Bug] duplicated long-form options go unnoticed Junio C Hamano
2026-02-27 19:27 ` [PATCH 1/2] pack-objects: remove duplicate --stdin-packs definition René Scharfe
2026-02-27 19:27 ` [PATCH 2/2] parseopt: check for duplicate long names and numerical options René Scharfe
2026-02-27 22:50 ` Jeff King
2026-02-27 23:08 ` Jeff King
2026-02-27 23:28 ` Junio C Hamano
2026-02-28 9:19 ` René Scharfe
2026-02-28 9:19 ` [PATCH v2 " René Scharfe
2026-02-28 10:58 ` Jeff King [this message]
2026-02-28 11:28 ` René Scharfe
2026-03-02 18:24 ` Jeff King
2026-03-01 14:33 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260228105849.GA3626520@coredump.intra.peff.net \
--to=peff@peff.net \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=l.s.r@web.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox