win32mbcs: add special wrapper for osutil.listdir().
authorShun-ichi GOTO <shunichi.goto@gmail.com>
Fri, 10 Jul 2009 19:34:08 +0900
changeset 9132 b47d7b440c5c
parent 9131 2bbb8419720d
child 9133 996c1cd8f530
win32mbcs: add special wrapper for osutil.listdir(). osutil.listdir() may misinterpret 0x5c of MBCS 2nd. byte as path separator. New wrapper prevents this by adding it beforehand.
hgext/win32mbcs.py
--- a/hgext/win32mbcs.py	Fri Jul 10 15:52:01 2009 +0900
+++ b/hgext/win32mbcs.py	Fri Jul 10 19:34:08 2009 +0900
@@ -69,6 +69,16 @@
             arg[k] = encode(v)
     return arg
 
+def appendsep(s):
+    # ensure the path ends with os.sep, appending it if necessary.
+    try:
+        us = decode(s)
+    except UnicodeError:
+        us = s
+    if us and us[-1] not in ':/\\':
+        s += os.sep
+    return s
+
 def wrapper(func, args, kwds):
     # check argument is unicode, then call original
     for arg in args:
@@ -79,12 +89,20 @@
         # convert arguments to unicode, call func, then convert back
         return encode(func(*decode(args), **decode(kwds)))
     except UnicodeError:
-        # If not encoded with encoding.encoding, report it then
-        # continue with calling original function.
-        raise util.Abort(_("[win32mbcs] filename conversion fail with"
+        raise util.Abort(_("[win32mbcs] filename conversion failed with"
                          " %s encoding\n") % (encoding.encoding))
 
-def wrapname(name):
+def wrapperforlistdir(func, args, kwds):
+    # Ensure 'path' argument ends with os.sep to avoids
+    # misinterpreting last 0x5c of MBCS 2nd byte as path separator.
+    if args:
+        args = list(args)
+        args[0] = appendsep(args[0])
+    if kwds.has_key('path'):
+        kwds['path'] = appendsep(kwds['path'])
+    return func(*args, **kwds)
+
+def wrapname(name, wrapper):
     module, name = name.rsplit('.', 1)
     module = sys.modules[module]
     func = getattr(module, name)
@@ -119,7 +137,8 @@
     # fake is only for relevant environment.
     if encoding.encoding.lower() in problematic_encodings.split():
         for f in funcs.split():
-            wrapname(f)
+            wrapname(f, wrapper)
+        wrapname("mercurial.osutil.listdir", wrapperforlistdir)
         ui.debug(_("[win32mbcs] activated with encoding: %s\n")
                  % encoding.encoding)