# HG changeset patch # User Shun-ichi GOTO # Date 2012-10-17 09:09:00 # Node ID 4091b0322918743c1860441a4e95c2d96542321c # Parent e4da793998bfdcfac5574bff640561dfc27ed7c6 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 --git a/hgext/win32mbcs.py b/hgext/win32mbcs.py --- a/hgext/win32mbcs.py +++ b/hgext/win32mbcs.py @@ -89,19 +89,28 @@ def appendsep(s): 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 +142,11 @@ funcs = '''os.path.join os.path.split os 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 +173,9 @@ def extsetup(ui): 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.