[PATCH 1 of 1] store: encode first space char in filenames (issue1713)

Adrian Buehlmann adrian at cadifra.com
Sat Aug 21 12:38:18 CDT 2010


# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1282408762 -7200
# Node ID 81918c77d3d7e3f4dcae03523f493c4363a9e9e3
# Parent  1fe4702fe2dfc3f3afcb43eac34692241fabf65e
store: encode first space char in filenames (issue1713)

Windows explorer of Windows 7 strips leading spaces of path elements of
filenames when copying trees.

Encode the first space of all path elements as '~32' for 'parentdelta'
repositories.

diff --git a/mercurial/store.py b/mercurial/store.py
--- a/mercurial/store.py
+++ b/mercurial/store.py
@@ -71,7 +71,7 @@ lowerencode = _build_lower_encodefun()
 _windows_reserved_filenames = '''con prn aux nul
     com1 com2 com3 com4 com5 com6 com7 com8 com9
     lpt1 lpt2 lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9'''.split()
-def auxencode(path):
+def _auxencode(path, encodefirstspace):
     res = []
     for n in path.split('/'):
         if n:
@@ -83,13 +83,15 @@ def auxencode(path):
             if n[-1] in '. ':
                 # encode last period or space ('foo...' -> 'foo..~2e')
                 n = n[:-1] + "~%02x" % ord(n[-1])
+            if encodefirstspace and n[0] == ' ':
+                n = '~32' + n[1:]
         res.append(n)
     return '/'.join(res)
 
 MAX_PATH_LEN_IN_HGSTORE = 120
 DIR_PREFIX_LEN = 8
 _MAX_SHORTENED_DIRS_LEN = 8 * (DIR_PREFIX_LEN + 1) - 4
-def hybridencode(path):
+def _hybridencode(path, auxencode):
     '''encodes path with a length limit
 
     Encodes all paths that begin with 'data/', according to the following.
@@ -282,7 +284,8 @@ class fncache(object):
         return iter(self.entries)
 
 class fncachestore(basicstore):
-    def __init__(self, path, opener, pathjoiner):
+    def __init__(self, path, opener, pathjoiner, encode):
+        self.encode = encode
         self.pathjoiner = pathjoiner
         self.path = self.pathjoiner(path, 'store')
         self.createmode = _calcmode(self.path)
@@ -294,11 +297,11 @@ class fncachestore(basicstore):
         def fncacheopener(path, mode='r', *args, **kw):
             if mode not in ('r', 'rb') and path.startswith('data/'):
                 fnc.add(path)
-            return op(hybridencode(path), mode, *args, **kw)
+            return op(self.encode(path), mode, *args, **kw)
         self.opener = fncacheopener
 
     def join(self, f):
-        return self.pathjoiner(self.path, hybridencode(f))
+        return self.pathjoiner(self.path, self.encode(f))
 
     def datafiles(self):
         rewrite = False
@@ -306,7 +309,7 @@ class fncachestore(basicstore):
         pjoin = self.pathjoiner
         spath = self.path
         for f in self.fncache:
-            ef = hybridencode(f)
+            ef = self.encode(f)
             try:
                 st = os.stat(pjoin(spath, ef))
                 yield f, ef, st.st_size
@@ -328,6 +331,9 @@ def store(requirements, path, opener, pa
     pathjoiner = pathjoiner or os.path.join
     if 'store' in requirements:
         if 'fncache' in requirements:
-            return fncachestore(path, opener, pathjoiner)
+            encodefirstspace = 'parentdelta' in requirements
+            auxencode = lambda f: _auxencode(f, encodefirstspace)
+            encode = lambda f: _hybridencode(f, auxencode)
+            return fncachestore(path, opener, pathjoiner, encode)
         return encodedstore(path, opener, pathjoiner)
     return basicstore(path, opener, pathjoiner)
diff --git a/tests/test-hybridencode.py b/tests/test-hybridencode.py
--- a/tests/test-hybridencode.py
+++ b/tests/test-hybridencode.py
@@ -2,7 +2,10 @@
 
 from mercurial import store
 
-enc = store.hybridencode # used for fncache repo format
+auxencode = lambda f: store._auxencode(f, True)
+hybridencode = lambda f: store._hybridencode(f, auxencode)
+
+enc = hybridencode # used for parentdelta repo format
 
 def show(s):
     print "A = '%s'" % s
diff --git a/tests/test-hybridencode.py.out b/tests/test-hybridencode.py.out
--- a/tests/test-hybridencode.py.out
+++ b/tests/test-hybridencode.py.out
@@ -17,5 +17,5 @@ A = 'data/Project.Planning/Resources/Ano
 B = 'dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilena0fd7c506f5c9d58204444fc67e9499006bd2d445.txt'
 
 A = 'data/foo.../foo   / /a./_. /__/.x../    bla/something.i'
-B = 'data/foo..~2e/foo  ~20/~20/a~2e/__.~20/____/.x.~2e/    bla/something.i'
+B = 'data/foo..~2e/foo  ~20/~20/a~2e/__.~20/____/.x.~2e/~32   bla/something.i'
 


More information about the Mercurial-devel mailing list