Patchwork [STABLE,V2] win32mbcs: avoid unintentional failure at colorization

login
register
mail settings
Submitter Katsunori FUJIWARA
Date May 31, 2017, 2:46 p.m.
Message ID <377c74ef008dcab7ee70.1496242013@speaknoevil>
Download mbox | patch
Permalink /patch/21089/
State Accepted
Headers show

Comments

Katsunori FUJIWARA - May 31, 2017, 2:46 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1496241873 -32400
#      Wed May 31 23:44:33 2017 +0900
# Branch stable
# Node ID 377c74ef008dcab7ee70897acca82fbf8ddee3f6
# Parent  387a76cac28e34b5fe49794fe7d79247b57ad61c
win32mbcs: avoid unintentional failure at colorization

Since 176ed32dc159, pycompat.bytestr() wrapped by win32mbcs returns
unicode object, if an argument is not byte-str object. And this causes
unexpected failure at colorization.

pycompat.bytestr() is used to convert from color effect "int" value to
byte-str object in color module. Wrapped pycompat.bytestr() returns
unicode object for such "int" value, because it isn't byte-str.

If this returned unicode object is used to colorize non-ASCII byte-str
in cases below, UnicodeDecodeError is raised at an operation between
them.

  - colorization uses "ansi" color mode, or

    Even though this isn't default on Windows, user might use this
    color mode for third party pager.

  - ui.write() is buffered with labeled=True

    Buffering causes "ansi" color mode internally, regardless of
    actual color mode. With "win32" color mode, extra escape sequences
    are omitted at writing data out.

    For example, with "win32" color mode, "hg status" doesn't fail for
    non-ASCII filenames, but "hg log" does for non-ASCII text, because
    the latter implies buffered formatter.

There are many "color effect" value lines in color.py, and making them
byte-str objects isn't suitable for fixing on stable. In addition to
it, pycompat.bytestr will be used to get byte-str object from any
types other than int, too.

To resolve this issue, this patch does:

  - replace pycompat.bytestr in checkwinfilename() with newly added
    hook point util._filenamebytestr, and

  - make win32mbcs reverse-wrap util._filenamebytestr
    (this is a replacement of 176ed32dc159)

This patch does two things above at same time, because separately
applying the former change adds broken revision (from point of view of
win32mbcs) to stable branch.

"_" prefix is added to "filenamebytestr", because it is win32mbcs
specific hook point.
Yuya Nishihara - May 31, 2017, 3:14 p.m.
On Wed, 31 May 2017 23:46:53 +0900, FUJIWARA Katsunori wrote:
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> # Date 1496241873 -32400
> #      Wed May 31 23:44:33 2017 +0900
> # Branch stable
> # Node ID 377c74ef008dcab7ee70897acca82fbf8ddee3f6
> # Parent  387a76cac28e34b5fe49794fe7d79247b57ad61c
> win32mbcs: avoid unintentional failure at colorization

Queued for stable, thanks!

Patch

diff --git a/hgext/win32mbcs.py b/hgext/win32mbcs.py
--- a/hgext/win32mbcs.py
+++ b/hgext/win32mbcs.py
@@ -156,7 +156,7 @@  funcs = '''os.path.join os.path.split os
 # because they expects argument is local encoded string and cause
 # problem with unicode string.
 rfuncs = '''mercurial.encoding.upper mercurial.encoding.lower
- mercurial.pycompat.bytestr'''
+ mercurial.util._filenamebytestr'''
 
 # List of Windows specific functions to be wrapped.
 winfuncs = '''os.path.splitunc'''
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -65,6 +65,9 @@  urlerr = pycompat.urlerr
 urlreq = pycompat.urlreq
 xmlrpclib = pycompat.xmlrpclib
 
+# workaround for win32mbcs
+_filenamebytestr = pycompat.bytestr
+
 def isatty(fp):
     try:
         return fp.isatty()
@@ -1224,7 +1227,7 @@  def checkwinfilename(path):
     for n in path.replace('\\', '/').split('/'):
         if not n:
             continue
-        for c in pycompat.bytestr(n):
+        for c in _filenamebytestr(n):
             if c in _winreservedchars:
                 return _("filename contains '%s', which is reserved "
                          "on Windows") % c