D299: pycompat: introduce a wrapper for __builtins__.{raw_,}input()

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: pycompat: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
durin42 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  In order to make this work, we have to wrap the io streams in a
  TextIOWrapper so that __builtins__.input() can do unicode IO on Python
 
  3. We can't just restore the original (unicode) sys.std* because we
 
  might be running a cmdserver, and if we blindly restore sys.* to the
  original values then we end up breaking the cmdserver. Sadly,
  TextIOWrapper tries to close the underlying stream during its __del__,
  so we have to make a sublcass to prevent that.
 
  If you see errors like:
 
  TypeError: a bytes-like object is required, not 'str'
 
  On an input() or print() call on Python 3, the substitution of
  sys.std* is probably the root cause.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

AFFECTED FILES
  hgext/hgk.py
  mercurial/pycompat.py
  mercurial/ui.py

CHANGE DETAILS

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1219,7 +1219,7 @@
         # prompt ' ' must exist; otherwise readline may delete entire line
         # - http://bugs.python.org/issue12833
         with self.timeblockedsection('stdio'):
-            line = raw_input(' ')
+            line = pycompat.bytesinput(r' ')
         sys.stdin = oldin
         sys.stdout = oldout
 
diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -69,6 +69,23 @@
     stdout = sys.stdout.buffer
     stderr = sys.stderr.buffer
 
+    class noclosetextio(io.TextIOWrapper):
+        def __del__(self):
+            """Override __del__ so it doesn't close the underlying stream."""
+
+    def bytesinput(*args, **kwargs):
+        origs = {}
+        try:
+            for stream in 'stdin stdout stderr'.split():
+                s = getattr(sys, stream)
+                origs[stream] = s
+                if not isinstance(s, io.TextIOBase):
+                    setattr(sys, stream, noclosetextio(s))
+            return bytestr(input(*args, **kwargs))
+        finally:
+            for stream, restore in origs.items():
+                setattr(sys, stream, restore)
+
     # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
     # we can use os.fsencode() to get back bytes argv.
     #
@@ -303,6 +320,7 @@
     stdin = sys.stdin
     stdout = sys.stdout
     stderr = sys.stderr
+    bytesinput = raw_input
     if getattr(sys, 'argv', None) is not None:
         sysargv = sys.argv
     sysplatform = sys.platform
diff --git a/hgext/hgk.py b/hgext/hgk.py
--- a/hgext/hgk.py
+++ b/hgext/hgk.py
@@ -48,6 +48,7 @@
     commands,
     obsolete,
     patch,
+    pycompat,
     registrar,
     scmutil,
 )
@@ -96,7 +97,7 @@
     while True:
         if opts['stdin']:
             try:
-                line = raw_input().split(' ')
+                line = pycompat.bytesinput().split(' ')
                 node1 = line[0]
                 if len(line) > 1:
                     node2 = line[1]
@@ -177,7 +178,7 @@
     prefix = ""
     if opts['stdin']:
         try:
-            (type, r) = raw_input().split(' ')
+            (type, r) = pycompat.bytesinput().split(' ')
             prefix = "    "
         except EOFError:
             return
@@ -195,7 +196,7 @@
         catcommit(ui, repo, n, prefix)
         if opts['stdin']:
             try:
-                (type, r) = raw_input().split(' ')
+                (type, r) = pycompat.bytesinput().split(' ')
             except EOFError:
                 break
         else:



To: durin42, #hg-reviewers
Cc: mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: pycompat: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
yuja added inline comments.

INLINE COMMENTS

> pycompat.py:84
> +                    setattr(sys, stream, noclosetextio(s))
> +            return bytestr(input(*args, **kwargs))
> +        finally:

Needs to specify encoding because user input may contain
non-ascii characters.

Perhaps it should be `noclosetextio(s, encoding=encoding.encoding)` and
`encoding.strtolocal(input(...))`.
Alternatively, forcing `latin-1` might work, but I'm not sure.

> ui.py:1222
>          with self.timeblockedsection('stdio'):
> -            line = raw_input(' ')
> +            line = pycompat.bytesinput(r' ')
>          sys.stdin = oldin

I think it's better to specify input and output explicitly.

`bytesinput(..., self.fin, self.fout)`

Setting BytesIO to `sys.stdin/stdout` is just plain wrong on Python 3.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: pycompat: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
durin42 marked an inline comment as done.
durin42 added inline comments.

INLINE COMMENTS

> yuja wrote in pycompat.py:84
> Needs to specify encoding because user input may contain
> non-ascii characters.
>
> Perhaps it should be `noclosetextio(s, encoding=encoding.encoding)` and
> `encoding.strtolocal(input(...))`.
> Alternatively, forcing `latin-1` might work, but I'm not sure.

Ugh, gross. I can't use encoding from pycompat, can I?

> yuja wrote in ui.py:1222
> I think it's better to specify input and output explicitly.
>
> `bytesinput(..., self.fin, self.fout)`
>
> Setting BytesIO to `sys.stdin/stdout` is just plain wrong on Python 3.

Yeah, it's pretty clowny.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: pycompat: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
durin42 updated this revision to Diff 801.
durin42 marked an inline comment as done.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D299?vs=682&id=801

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

AFFECTED FILES
  hgext/hgk.py
  mercurial/pycompat.py
  mercurial/ui.py

CHANGE DETAILS

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1217,18 +1217,10 @@
         self.write(prompt, prompt=True)
         self.flush()
 
-        # instead of trying to emulate raw_input, swap (self.fin,
-        # self.fout) with (sys.stdin, sys.stdout)
-        oldin = sys.stdin
-        oldout = sys.stdout
-        sys.stdin = self.fin
-        sys.stdout = self.fout
         # prompt ' ' must exist; otherwise readline may delete entire line
         # - http://bugs.python.org/issue12833
         with self.timeblockedsection('stdio'):
-            line = raw_input(' ')
-        sys.stdin = oldin
-        sys.stdout = oldout
+            line = pycompat.bytesinput(self.fin, self.fout, r' ')
 
         # When stdin is in binary mode on Windows, it can cause
         # raw_input() to emit an extra trailing carriage return
diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -70,6 +70,18 @@
     stdout = sys.stdout.buffer
     stderr = sys.stderr.buffer
 
+    class noclosetextio(io.TextIOWrapper):
+        def __del__(self):
+            """Override __del__ so it doesn't close the underlying stream."""
+
+    def bytesinput(fin, fout, *args, **kwargs):
+        sin, sout = sys.stdin, sys.stdout
+        try:
+            sys.stdin, sys.stdout = noclosetextio(fin), noclosetextio(fout)
+            return bytestr(input(*args, **kwargs))
+        finally:
+            sys.stdin, sys.stdout = sin, sout
+
     # Since Python 3 converts argv to wchar_t type by Py_DecodeLocale() on Unix,
     # we can use os.fsencode() to get back bytes argv.
     #
@@ -304,6 +316,15 @@
     stdin = sys.stdin
     stdout = sys.stdout
     stderr = sys.stderr
+
+    def bytesinput(fin, fout, *args, **kwargs):
+        sin, sout = sys.stdin, sys.stdout
+        try:
+            sys.stdin, sys.stdout = fin, fout
+            return raw_input(*args, **kwargs)
+        finally:
+            sys.stdin, sys.stdout = sin, sout
+
     if getattr(sys, 'argv', None) is not None:
         sysargv = sys.argv
     sysplatform = sys.platform
diff --git a/hgext/hgk.py b/hgext/hgk.py
--- a/hgext/hgk.py
+++ b/hgext/hgk.py
@@ -48,6 +48,7 @@
     commands,
     obsolete,
     patch,
+    pycompat,
     registrar,
     scmutil,
 )
@@ -96,7 +97,7 @@
     while True:
         if opts['stdin']:
             try:
-                line = raw_input().split(' ')
+                line = pycompat.bytesinput(sys.stdin, sys.stdout).split(' ')
                 node1 = line[0]
                 if len(line) > 1:
                     node2 = line[1]
@@ -177,7 +178,7 @@
     prefix = ""
     if opts['stdin']:
         try:
-            (type, r) = raw_input().split(' ')
+            (type, r) = pycompat.bytesinput(sys.stdin, sys.stdout).split(' ')
             prefix = "    "
         except EOFError:
             return
@@ -195,7 +196,8 @@
         catcommit(ui, repo, n, prefix)
         if opts['stdin']:
             try:
-                (type, r) = raw_input().split(' ')
+                (type, r) = pycompat.bytesinput(
+                    sys.stdin, sys.stdout).split(' ')
             except EOFError:
                 break
         else:



To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: pycompat: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
yuja added inline comments.

INLINE COMMENTS

> hgk.py:100
>              try:
> -                line = raw_input().split(' ')
> +                line = pycompat.bytesinput(sys.stdin, sys.stdout).split(' ')
>                  node1 = line[0]

Perhaps hgk should use ui.fin and ui.fout.

> durin42 wrote in pycompat.py:84
> Ugh, gross. I can't use encoding from pycompat, can I?

Nah. So this could be `util.bytesinput(fin, fout)` and `encoding.strio()`.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: py3: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
durin42 updated this revision to Diff 948.
durin42 edited the summary of this revision.
durin42 retitled this revision from "pycompat: introduce a wrapper for __builtins__.{raw_,}input()" to "py3: introduce a wrapper for __builtins__.{raw_,}input()".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D299?vs=801&id=948

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

AFFECTED FILES
  hgext/hgk.py
  mercurial/encoding.py
  mercurial/pycompat.py
  mercurial/ui.py
  mercurial/util.py

CHANGE DETAILS

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -172,6 +172,18 @@
 def safehasattr(thing, attr):
     return getattr(thing, attr, _notset) is not _notset
 
+def bytesinput(fin, fout, *args, **kwargs):
+    sin, sout = sys.stdin, sys.stdout
+    try:
+        if pycompat.ispy3:
+            sys.stdin, sys.stdout = encoding.strio(fin), encoding.strio(fout)
+            return pycompat.bytestr(input(*args, **kwargs))
+        else:
+            sys.stdin, sys.stdout = fin, fout
+            return raw_input(*args, **kwargs)
+    finally:
+        sys.stdin, sys.stdout = sin, sout
+
 def bitsfrom(container):
     bits = 0
     for bit in container:
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1217,18 +1217,10 @@
         self.write(prompt, prompt=True)
         self.flush()
 
-        # instead of trying to emulate raw_input, swap (self.fin,
-        # self.fout) with (sys.stdin, sys.stdout)
-        oldin = sys.stdin
-        oldout = sys.stdout
-        sys.stdin = self.fin
-        sys.stdout = self.fout
         # prompt ' ' must exist; otherwise readline may delete entire line
         # - http://bugs.python.org/issue12833
         with self.timeblockedsection('stdio'):
-            line = raw_input(' ')
-        sys.stdin = oldin
-        sys.stdout = oldout
+            line = util.bytesinput(self.fin, self.fout, r' ')
 
         # When stdin is in binary mode on Windows, it can cause
         # raw_input() to emit an extra trailing carriage return
diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -304,6 +304,7 @@
     stdin = sys.stdin
     stdout = sys.stdout
     stderr = sys.stderr
+
     if getattr(sys, 'argv', None) is not None:
         sysargv = sys.argv
     sysplatform = sys.platform
diff --git a/mercurial/encoding.py b/mercurial/encoding.py
--- a/mercurial/encoding.py
+++ b/mercurial/encoding.py
@@ -8,6 +8,7 @@
 from __future__ import absolute_import
 
 import array
+import io
 import locale
 import os
 import unicodedata
@@ -573,3 +574,16 @@
             c = chr(ord(c.decode("utf-8")) & 0xff)
         r += c
     return r
+
+class strio(io.TextIOWrapper):
+    """Wrapper around TextIOWrapper that respects hg's encoding assumptions.
+
+    Also works around Python closing streams.
+    """
+
+    def __init__(self, buffer, **kwargs):
+        kwargs[r'encoding'] = encoding
+        super(strio, self).__init__(buffer, **kwargs)
+
+    def __del__(self):
+        """Override __del__ so it doesn't close the underlying stream."""
diff --git a/hgext/hgk.py b/hgext/hgk.py
--- a/hgext/hgk.py
+++ b/hgext/hgk.py
@@ -50,6 +50,7 @@
     patch,
     registrar,
     scmutil,
+    util,
 )
 
 cmdtable = {}
@@ -96,7 +97,7 @@
     while True:
         if opts['stdin']:
             try:
-                line = raw_input().split(' ')
+                line = util.bytesinput(ui.fin, ui.fout).split(' ')
                 node1 = line[0]
                 if len(line) > 1:
                     node2 = line[1]
@@ -177,7 +178,7 @@
     prefix = ""
     if opts['stdin']:
         try:
-            (type, r) = raw_input().split(' ')
+            (type, r) = util.bytesinput(ui.fin, ui.fout).split(' ')
             prefix = "    "
         except EOFError:
             return
@@ -195,7 +196,7 @@
         catcommit(ui, repo, n, prefix)
         if opts['stdin']:
             try:
-                (type, r) = raw_input().split(' ')
+                (type, r) = util.bytesinput(ui.fin, ui.fout).split(' ')
             except EOFError:
                 break
         else:



To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: py3: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
durin42 marked 5 inline comments as done.
durin42 added inline comments.

INLINE COMMENTS

> yuja wrote in pycompat.py:84
> Nah. So this could be `util.bytesinput(fin, fout)` and `encoding.strio()`.

Sigh. I'm not sure I got the encoding.py bit quite right, take a look?

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

To: durin42, #hg-reviewers
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: py3: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
yuja accepted this revision.
yuja added inline comments.
This revision is now accepted and ready to land.

INLINE COMMENTS

> util.py:180
> +            sys.stdin, sys.stdout = encoding.strio(fin), encoding.strio(fout)
> +            return pycompat.bytestr(input(*args, **kwargs))
> +        else:

s/pycompat.bytestr/encoding.strtolocal/ and queued, thanks.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

To: durin42, #hg-reviewers, yuja
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: py3: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
This revision was automatically updated to reflect the committed changes.
durin42 marked an inline comment as done.
Closed by commit rHGd390726b575d: py3: introduce a wrapper for __builtins__.{raw_,}input() (authored by durin42).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D299?vs=948&id=971#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D299?vs=948&id=971

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

AFFECTED FILES
  hgext/hgk.py
  mercurial/encoding.py
  mercurial/ui.py
  mercurial/util.py

CHANGE DETAILS

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -172,6 +172,18 @@
 def safehasattr(thing, attr):
     return getattr(thing, attr, _notset) is not _notset
 
+def bytesinput(fin, fout, *args, **kwargs):
+    sin, sout = sys.stdin, sys.stdout
+    try:
+        if pycompat.ispy3:
+            sys.stdin, sys.stdout = encoding.strio(fin), encoding.strio(fout)
+            return encoding.strtolocal(input(*args, **kwargs))
+        else:
+            sys.stdin, sys.stdout = fin, fout
+            return raw_input(*args, **kwargs)
+    finally:
+        sys.stdin, sys.stdout = sin, sout
+
 def bitsfrom(container):
     bits = 0
     for bit in container:
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1217,18 +1217,10 @@
         self.write(prompt, prompt=True)
         self.flush()
 
-        # instead of trying to emulate raw_input, swap (self.fin,
-        # self.fout) with (sys.stdin, sys.stdout)
-        oldin = sys.stdin
-        oldout = sys.stdout
-        sys.stdin = self.fin
-        sys.stdout = self.fout
         # prompt ' ' must exist; otherwise readline may delete entire line
         # - http://bugs.python.org/issue12833
         with self.timeblockedsection('stdio'):
-            line = raw_input(' ')
-        sys.stdin = oldin
-        sys.stdout = oldout
+            line = util.bytesinput(self.fin, self.fout, r' ')
 
         # When stdin is in binary mode on Windows, it can cause
         # raw_input() to emit an extra trailing carriage return
diff --git a/mercurial/encoding.py b/mercurial/encoding.py
--- a/mercurial/encoding.py
+++ b/mercurial/encoding.py
@@ -8,6 +8,7 @@
 from __future__ import absolute_import
 
 import array
+import io
 import locale
 import os
 import unicodedata
@@ -573,3 +574,16 @@
             c = chr(ord(c.decode("utf-8")) & 0xff)
         r += c
     return r
+
+class strio(io.TextIOWrapper):
+    """Wrapper around TextIOWrapper that respects hg's encoding assumptions.
+
+    Also works around Python closing streams.
+    """
+
+    def __init__(self, buffer, **kwargs):
+        kwargs[r'encoding'] = encoding
+        super(strio, self).__init__(buffer, **kwargs)
+
+    def __del__(self):
+        """Override __del__ so it doesn't close the underlying stream."""
diff --git a/hgext/hgk.py b/hgext/hgk.py
--- a/hgext/hgk.py
+++ b/hgext/hgk.py
@@ -50,6 +50,7 @@
     patch,
     registrar,
     scmutil,
+    util,
 )
 
 cmdtable = {}
@@ -96,7 +97,7 @@
     while True:
         if opts['stdin']:
             try:
-                line = raw_input().split(' ')
+                line = util.bytesinput(ui.fin, ui.fout).split(' ')
                 node1 = line[0]
                 if len(line) > 1:
                     node2 = line[1]
@@ -177,7 +178,7 @@
     prefix = ""
     if opts['stdin']:
         try:
-            (type, r) = raw_input().split(' ')
+            (type, r) = util.bytesinput(ui.fin, ui.fout).split(' ')
             prefix = "    "
         except EOFError:
             return
@@ -195,7 +196,7 @@
         catcommit(ui, repo, n, prefix)
         if opts['stdin']:
             try:
-                (type, r) = raw_input().split(' ')
+                (type, r) = util.bytesinput(ui.fin, ui.fout).split(' ')
             except EOFError:
                 break
         else:



To: durin42, #hg-reviewers, yuja
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

D299: py3: introduce a wrapper for __builtins__.{raw_,}input()

dsp (David Soria Parra)
In reply to this post by dsp (David Soria Parra)
yuja added inline comments.

INLINE COMMENTS

> encoding.py:585
> +    def __init__(self, buffer, **kwargs):
> +        kwargs[r'encoding'] = encoding
> +        super(strio, self).__init__(buffer, **kwargs)

Fixed as `s/encoding/_sysstr(encoding)/`.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D299

To: durin42, #hg-reviewers, yuja
Cc: yuja, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Loading...