Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/util.py @ 32131:377c74ef008d stable
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.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Wed, 31 May 2017 23:44:33 +0900 |
parents | a34b5e7c6683 |
children | 9929af2b09b4 53224b1ffbc2 |
comparison
equal
deleted
inserted
replaced
32130:387a76cac28e | 32131:377c74ef008d |
---|---|
62 stdout = pycompat.stdout | 62 stdout = pycompat.stdout |
63 stringio = pycompat.stringio | 63 stringio = pycompat.stringio |
64 urlerr = pycompat.urlerr | 64 urlerr = pycompat.urlerr |
65 urlreq = pycompat.urlreq | 65 urlreq = pycompat.urlreq |
66 xmlrpclib = pycompat.xmlrpclib | 66 xmlrpclib = pycompat.xmlrpclib |
67 | |
68 # workaround for win32mbcs | |
69 _filenamebytestr = pycompat.bytestr | |
67 | 70 |
68 def isatty(fp): | 71 def isatty(fp): |
69 try: | 72 try: |
70 return fp.isatty() | 73 return fp.isatty() |
71 except AttributeError: | 74 except AttributeError: |
1222 if '\\/' in path: | 1225 if '\\/' in path: |
1223 return _("directory name ends with '\\', which is invalid on Windows") | 1226 return _("directory name ends with '\\', which is invalid on Windows") |
1224 for n in path.replace('\\', '/').split('/'): | 1227 for n in path.replace('\\', '/').split('/'): |
1225 if not n: | 1228 if not n: |
1226 continue | 1229 continue |
1227 for c in pycompat.bytestr(n): | 1230 for c in _filenamebytestr(n): |
1228 if c in _winreservedchars: | 1231 if c in _winreservedchars: |
1229 return _("filename contains '%s', which is reserved " | 1232 return _("filename contains '%s', which is reserved " |
1230 "on Windows") % c | 1233 "on Windows") % c |
1231 if ord(c) <= 31: | 1234 if ord(c) <= 31: |
1232 return _("filename contains %r, which is invalid " | 1235 return _("filename contains %r, which is invalid " |