[PATCH STABLE] win32mbcs: add reversing wrapper for some unicode-incompatible functions

Shun-ichi Goto shunichi.goto at gmail.com
Wed Oct 17 19:42:35 CDT 2012


# HG changeset patch
# User Shun-ichi GOTO <shunichi.goto at gmail.com>
# Date 1350520891 -32400
# Node ID 0e61a8fe5015fc0ca0eb7caabbf355ee84378472
# Parent  72c234081ae1350220132c69750f5a093902a1e7
win32mbcs: add reversing wrapper for some unicode-incompatible functions.

This changeset fix the problem to use win32mbcs with mercurial 2.3 or
later.

The problem is brought by side effect of modification of
encoding.upper() (changeset 17236:9fb8312dbdbd) because upper() does
not accept unicode string argument. So wrapped util.normcase() which
uses upper() will fail. In other words, upper() and lower() are
unicode incompatible.

To fix this issue, this changeset adds new wrapper for reversed
conversion (unicode to str) for lower() and upper() to use them
safely.

diff -r 72c234081ae1 -r 0e61a8fe5015 hgext/win32mbcs.py
--- a/hgext/win32mbcs.py	Mon Oct 15 17:43:05 2012 +0200
+++ b/hgext/win32mbcs.py	Thu Oct 18 09:41:31 2012 +0900
@@ -89,19 +89,26 @@
         s += os.sep
     return s
 
-def wrapper(func, args, kwds):
-    # check argument is unicode, then call original
+def basewrapper(func, argtype, enc, dec, args, kwds):
+    # check check already converted, then call original
     for arg in args:
-        if isinstance(arg, unicode):
+        if isinstance(arg, argtype):
             return func(*args, **kwds)
 
     try:
-        # convert arguments to unicode, call func, then convert back
-        return encode(func(*decode(args), **decode(kwds)))
+        # convert string arguments, call func, then convert back the
+        # return value.
+        return enc(func(*dec(args), **dec(kwds)))
     except UnicodeError:
         raise util.Abort(_("[win32mbcs] filename conversion failed with"
                          " %s encoding\n") % (_encoding))
 
+def wrapper(func, args, kwds):
+    return basewrapper(func, unicode, encode, decode, args, kwds)
+
+def reversewrapper(func, args, kwds):
+    return basewrapper(func, str, decode, encode, args, kwds)
+
 def wrapperforlistdir(func, args, kwds):
     # Ensure 'path' argument ends with os.sep to avoids
     # misinterpreting last 0x5c of MBCS 2nd byte as path separator.
@@ -133,6 +140,11 @@
  mercurial.util.fspath mercurial.util.pconvert mercurial.util.normpath
  mercurial.util.checkwinfilename mercurial.util.checkosfilename'''
 
+# These functions are required to be called with local encoded string
+# because they expects argument is local encoded string and cause
+# problem with unicode string.
+rfuncs = '''mercurial.encoding.upper mercurial.encoding.lower'''
+
 # List of Windows specific functions to be wrapped.
 winfuncs = '''os.path.splitunc'''
 
@@ -159,6 +171,9 @@
             for f in winfuncs.split():
                 wrapname(f, wrapper)
         wrapname("mercurial.osutil.listdir", wrapperforlistdir)
+        # wrap functions to be called with local byte string arguments
+        for f in rfuncs.split():
+            wrapname(f, reversewrapper)
         # Check sys.args manually instead of using ui.debug() because
         # command line options is not yet applied when
         # extensions.loadall() is called.


More information about the Mercurial-devel mailing list