dispatch: restore `--config` can't be abbreviated message in case of ambiguity
authorMatt Harbison <matt_harbison@yahoo.com>
Thu, 06 Feb 2025 00:56:25 -0500
changeset 52745 8780d5707812
parent 52744 25b344f2aeef
child 52746 4c99bb87891b
dispatch: restore `--config` can't be abbreviated message in case of ambiguity This feels kind of gross, in part because it's a surprising amount of code for a specific edge case, and in part because it assumes some implementation details. But I don't see a better way, since `getopt.long_has_args()` will create a list of all known long options that start with the current option, and raise errors of this type if the list is either empty or has more than one element. There's not a programmatic way to tell the difference between these two aside from parsing the message, so we replicate the check here and raise the expected exception in the case of ambiguity. Otherwise, the original expection is re-raised.
mercurial/dispatch.py
tests/test-globalopts.t
--- a/mercurial/dispatch.py	Wed Jan 29 16:09:06 2025 -0500
+++ b/mercurial/dispatch.py	Thu Feb 06 00:56:25 2025 -0500
@@ -1151,7 +1151,22 @@
             encoding.fallbackencoding = fallback
 
         fullargs = args
-        cmd, func, args, options, cmdoptions = _parse(lui, args)
+        try:
+            cmd, func, args, options, cmdoptions = _parse(lui, args)
+        except error.CommandError as e:
+            cause = e.__context__
+            if isinstance(cause, getopt.GetoptError):
+                if cause.opt and "config".startswith(cause.opt):
+                    # pycompat._getoptbwrapper() decodes bytes with latin-1
+                    opt = cause.opt.encode('latin-1')
+                    all_long = {o[1] for o in commands.globalopts}
+                    possible = [o for o in all_long if o.startswith(opt)]
+
+                    if len(possible) != 1:
+                        raise error.InputError(
+                            _(b"option --config may not be abbreviated")
+                        )
+            raise
 
         # store the canonical command name in request object for later access
         req.canonical_command = cmd
--- a/tests/test-globalopts.t	Wed Jan 29 16:09:06 2025 -0500
+++ b/tests/test-globalopts.t	Thu Feb 06 00:56:25 2025 -0500
@@ -138,8 +138,7 @@
 earlygetopt with illegal abbreviations:
 
   $ hg --confi "foo.bar=baz"
-  hg: option --confi not a unique prefix
-  (use 'hg help -v' for a list of global options)
+  abort: option --config may not be abbreviated
   [10]
   $ hg --config-f "foo"
   abort: option --config-file may not be abbreviated