Patchwork [4,of,5] fancyopts: use getopt.gnu_getopt()

login
register
mail settings
Submitter Yuya Nishihara
Date Dec. 2, 2017, 7 a.m.
Message ID <8dd510eb51942ddae4dc.1512198042@mimosa>
Download mbox | patch
Permalink /patch/25894/
State Accepted
Headers show

Comments

Yuya Nishihara - Dec. 2, 2017, 7 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1511453340 -32400
#      Fri Nov 24 01:09:00 2017 +0900
# Node ID 8dd510eb51942ddae4dc69423627a349656d25f0
# Parent  eaa3dd26e7da4b6ab73c9b124697a607324bef36
fancyopts: use getopt.gnu_getopt()

The issue described in the docstring has been fixed since Python 20ab2260dc93,
which is in 2.7.

https://hg.python.org/cpython/rev/20ab2260dc93
https://bugs.python.org/issue4458

This fixes the handling of '--' value.

Patch

diff --git a/mercurial/fancyopts.py b/mercurial/fancyopts.py
--- a/mercurial/fancyopts.py
+++ b/mercurial/fancyopts.py
@@ -199,33 +199,6 @@  def earlygetopt(args, shortlist, namelis
     parsedargs.extend(args[argcount + (not keepsep):])
     return parsedopts, parsedargs
 
-def gnugetopt(args, options, longoptions):
-    """Parse options mostly like getopt.gnu_getopt.
-
-    This is different from getopt.gnu_getopt in that an argument of - will
-    become an argument of - instead of vanishing completely.
-    """
-    extraargs = []
-    if '--' in args:
-        stopindex = args.index('--')
-        extraargs = args[stopindex + 1:]
-        args = args[:stopindex]
-    opts, parseargs = pycompat.getoptb(args, options, longoptions)
-    args = []
-    while parseargs:
-        arg = parseargs.pop(0)
-        if arg and arg[0:1] == '-' and len(arg) > 1:
-            parseargs.insert(0, arg)
-            topts, newparseargs = pycompat.getoptb(parseargs,\
-                                            options, longoptions)
-            opts = opts + topts
-            parseargs = newparseargs
-        else:
-            args.append(arg)
-    args.extend(extraargs)
-    return opts, args
-
-
 def fancyopts(args, options, state, gnu=False, early=False, optaliases=None):
     """
     read args, parse options, and store options in state
@@ -312,7 +285,7 @@  def fancyopts(args, options, state, gnu=
     if early:
         parse = functools.partial(earlygetopt, gnu=gnu)
     elif gnu:
-        parse = gnugetopt
+        parse = pycompat.gnugetoptb
     else:
         parse = pycompat.getoptb
     opts, args = parse(args, shortlist, namelist)
diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -214,7 +214,7 @@  if ispy3:
     def open(name, mode='r', buffering=-1):
         return builtins.open(name, sysstr(mode), buffering)
 
-    def getoptb(args, shortlist, namelist):
+    def _getoptbwrapper(orig, args, shortlist, namelist):
         """
         Takes bytes arguments, converts them to unicode, pass them to
         getopt.getopt(), convert the returned values back to bytes and then
@@ -224,7 +224,7 @@  if ispy3:
         args = [a.decode('latin-1') for a in args]
         shortlist = shortlist.decode('latin-1')
         namelist = [a.decode('latin-1') for a in namelist]
-        opts, args = getopt.getopt(args, shortlist, namelist)
+        opts, args = orig(args, shortlist, namelist)
         opts = [(a[0].encode('latin-1'), a[1].encode('latin-1'))
                 for a in opts]
         args = [a.encode('latin-1') for a in args]
@@ -291,8 +291,8 @@  else:
     def getdoc(obj):
         return getattr(obj, '__doc__', None)
 
-    def getoptb(args, shortlist, namelist):
-        return getopt.getopt(args, shortlist, namelist)
+    def _getoptbwrapper(orig, args, shortlist, namelist):
+        return orig(args, shortlist, namelist)
 
     strkwargs = identity
     byteskwargs = identity
@@ -320,3 +320,9 @@  isjython = sysplatform.startswith('java'
 isdarwin = sysplatform == 'darwin'
 isposix = osname == 'posix'
 iswindows = osname == 'nt'
+
+def getoptb(args, shortlist, namelist):
+    return _getoptbwrapper(getopt.getopt, args, shortlist, namelist)
+
+def gnugetoptb(args, shortlist, namelist):
+    return _getoptbwrapper(getopt.gnu_getopt, args, shortlist, namelist)
diff --git a/tests/test-dispatch.t b/tests/test-dispatch.t
--- a/tests/test-dispatch.t
+++ b/tests/test-dispatch.t
@@ -37,10 +37,17 @@  Missing parameter for early option:
   hg log [OPTION]... [FILE]
   (use 'hg log -h' to show more help)
 
-  $ hg log -R -- 2>&1 | grep 'hg log'
-  hg log: option -R requires argument
-  hg log [OPTION]... [FILE]
-  (use 'hg log -h' to show more help)
+"--" may be an option value:
+
+  $ hg -R -- log
+  abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
+  [255]
+  $ hg log -R --
+  abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
+  [255]
+  $ hg log -T --
+  -- (no-eol)
+  $ hg log -T -- -k nomatch
 
 Parsing of early options should stop at "--":