Merge with crew-stable
authorMatt Mackall <mpm@selenic.com>
Mon, 20 Jul 2009 19:15:44 -0500
changeset 9177 41bc92142f06
parent 9173 fe160ba4c976 (diff)
parent 9176 d12e9b40e444 (current diff)
child 9181 8864112d4f57
child 9182 3a319bc8906d
Merge with crew-stable
--- a/hgext/win32mbcs.py	Sun Jul 19 18:59:19 2009 +0200
+++ b/hgext/win32mbcs.py	Mon Jul 20 19:15:44 2009 -0500
@@ -52,6 +52,9 @@
         return tuple(map(decode, arg))
     elif isinstance(arg, list):
         return map(decode, arg)
+    elif isinstance(arg, dict):
+        for k, v in arg.items():
+            arg[k] = decode(v)
     return arg
 
 def encode(arg):
@@ -61,29 +64,50 @@
         return tuple(map(encode, arg))
     elif isinstance(arg, list):
         return map(encode, arg)
+    elif isinstance(arg, dict):
+        for k, v in arg.items():
+            arg[k] = encode(v)
     return arg
 
-def wrapper(func, args):
+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:
         if isinstance(arg, unicode):
-            return func(*args)
+            return func(*args, **kwds)
 
     try:
         # convert arguments to unicode, call func, then convert back
-        return encode(func(*decode(args)))
+        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)
-    def f(*args):
-        return wrapper(func, args)
+    def f(*args, **kwds):
+        return wrapper(func, args, kwds)
     try:
         f.__name__ = func.__name__                # fail with python23
     except Exception:
@@ -113,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)
 
--- a/mercurial/store.py	Sun Jul 19 18:59:19 2009 +0200
+++ b/mercurial/store.py	Mon Jul 20 19:15:44 2009 -0500
@@ -284,16 +284,17 @@
         self.pathjoiner = pathjoiner
         self.path = self.pathjoiner(path, 'store')
         self.createmode = _calcmode(self.path)
-        self._op = opener(self.path)
-        self._op.createmode = self.createmode
-        self.fncache = fncache(self._op)
+        op = opener(self.path)
+        op.createmode = self.createmode
+        fnc = fncache(op)
+        self.fncache = fnc
 
         def fncacheopener(path, mode='r', *args, **kw):
             if (mode not in ('r', 'rb')
                 and path.startswith('data/')
-                and path not in self.fncache):
-                    self.fncache.add(path)
-            return self._op(hybridencode(path), mode, *args, **kw)
+                and path not in fnc):
+                    fnc.add(path)
+            return op(hybridencode(path), mode, *args, **kw)
         self.opener = fncacheopener
 
     def join(self, f):