merge with main
authorThomas Arendsen Hein <thomas@intevation.de>
Tue, 18 Sep 2012 15:30:22 +0200
changeset 17595 741e2bef4155
parent 17593 9e31a72bede7 (diff)
parent 17583 55724f42fa14 (current diff)
child 17596 2eac9641496d
merge with main
--- a/mercurial/store.py	Mon Sep 17 15:13:17 2012 -0500
+++ b/mercurial/store.py	Tue Sep 18 15:30:22 2012 +0200
@@ -22,8 +22,6 @@
     >>> encodedir('data/foo.i.hg/bla.i')
     'data/foo.i.hg.hg/bla.i'
     '''
-    if not path.startswith('data/'):
-        return path
     return (path
             .replace(".hg/", ".hg.hg/")
             .replace(".i/", ".i.hg/")
@@ -38,7 +36,7 @@
     >>> decodedir('data/foo.i.hg.hg/bla.i')
     'data/foo.i.hg/bla.i'
     '''
-    if not path.startswith('data/') or ".hg/" not in path:
+    if ".hg/" not in path:
         return path
     return (path
             .replace(".d.hg/", ".d/")
@@ -132,22 +130,23 @@
     basename (e.g. "aux", "aux.foo"). A directory or file named "foo.aux"
     doesn't need encoding.
 
-    >>> _auxencode('.foo/aux.txt/txt.aux/con/prn/nul/foo.', True)
+    >>> s = '.foo/aux.txt/txt.aux/con/prn/nul/foo.'
+    >>> _auxencode(s.split('/'), True)
     ['~2efoo', 'au~78.txt', 'txt.aux', 'co~6e', 'pr~6e', 'nu~6c', 'foo~2e']
-    >>> _auxencode('.com1com2/lpt9.lpt4.lpt1/conprn/com0/lpt0/foo.', False)
+    >>> s = '.com1com2/lpt9.lpt4.lpt1/conprn/com0/lpt0/foo.'
+    >>> _auxencode(s.split('/'), False)
     ['.com1com2', 'lp~749.lpt4.lpt1', 'conprn', 'com0', 'lpt0', 'foo~2e']
-    >>> _auxencode('foo. ', True)
+    >>> _auxencode(['foo. '], True)
     ['foo.~20']
-    >>> _auxencode(' .foo', True)
+    >>> _auxencode([' .foo'], True)
     ['~20.foo']
     '''
-    res = path.split('/')
-    for i, n in enumerate(res):
+    for i, n in enumerate(path):
         if not n:
             continue
         if dotencode and n[0] in '. ':
             n = "~%02x" % ord(n[0]) + n[1:]
-            res[i] = n
+            path[i] = n
         else:
             l = n.find('.')
             if l == -1:
@@ -158,16 +157,16 @@
                 # encode third letter ('aux' -> 'au~78')
                 ec = "~%02x" % ord(n[2])
                 n = n[0:2] + ec + n[3:]
-                res[i] = n
+                path[i] = n
         if n[-1] in '. ':
             # encode last period or space ('foo...' -> 'foo..~2e')
-            res[i] = n[:-1] + "~%02x" % ord(n[-1])
-    return res
+            path[i] = n[:-1] + "~%02x" % ord(n[-1])
+    return path
 
 _maxstorepathlen = 120
 _dirprefixlen = 8
 _maxshortdirslen = 8 * (_dirprefixlen + 1) - 4
-def _hybridencode(path, auxencode):
+def _hybridencode(path, dotencode):
     '''encodes path with a length limit
 
     Encodes all paths that begin with 'data/', according to the following.
@@ -198,27 +197,30 @@
     The string 'data/' at the beginning is replaced with 'dh/', if the hashed
     encoding was used.
     '''
-    if not path.startswith('data/'):
-        return path
-    # escape directories ending with .i and .d
-    path = encodedir(path)
-    ndpath = path[len('data/'):]
-    res = 'data/' + '/'.join(auxencode(encodefilename(ndpath)))
+    ef = encodefilename(path).split('/')
+    res = '/'.join(_auxencode(ef, dotencode))
     if len(res) > _maxstorepathlen:
+        path = encodedir(path)
         digest = _sha(path).hexdigest()
-        parts = auxencode(lowerencode(ndpath))
-        _root, ext = os.path.splitext(parts[-1])
+        le = lowerencode(path).split('/')[1:]
+        parts = _auxencode(le, dotencode)
         basename = parts[-1]
+        _root, ext = os.path.splitext(basename)
         sdirs = []
+        sdirslen = 0
         for p in parts[:-1]:
             d = p[:_dirprefixlen]
             if d[-1] in '. ':
                 # Windows can't access dirs ending in period or space
                 d = d[:-1] + '_'
-            t = '/'.join(sdirs) + '/' + d
-            if len(t) > _maxshortdirslen:
-                break
+            if sdirslen == 0:
+                t = len(d)
+            else:
+                t = sdirslen + 1 + len(d)
+                if t > _maxshortdirslen:
+                    break
             sdirs.append(d)
+            sdirslen = t
         dirs = '/'.join(sdirs)
         if len(dirs) > 0:
             dirs += '/'
@@ -346,7 +348,7 @@
     def _write(self, files, atomictemp):
         fp = self.opener('fncache', mode='wb', atomictemp=atomictemp)
         if files:
-            fp.write('\n'.join(map(encodedir, files)) + '\n')
+            fp.write(encodedir('\n'.join(files) + '\n'))
         fp.close()
         self._dirty = False
 
@@ -394,8 +396,18 @@
             self.fncache.add(path)
         return self.opener(self.encode(path), mode, *args, **kw)
 
+def _plainhybridencode(f):
+    return _hybridencode(f, False)
+
+def _dothybridencode(f):
+    return _hybridencode(f, True)
+
 class fncachestore(basicstore):
-    def __init__(self, path, openertype, encode):
+    def __init__(self, path, openertype, dotencode):
+        if dotencode:
+            encode = _dothybridencode
+        else:
+            encode = _plainhybridencode
         self.encode = encode
         self.path = path + '/store'
         self.pathsep = self.path + '/'
@@ -442,8 +454,6 @@
 def store(requirements, path, openertype):
     if 'store' in requirements:
         if 'fncache' in requirements:
-            auxencode = lambda f: _auxencode(f, 'dotencode' in requirements)
-            encode = lambda f: _hybridencode(f, auxencode)
-            return fncachestore(path, openertype, encode)
+            return fncachestore(path, openertype, 'dotencode' in requirements)
         return encodedstore(path, openertype)
     return basicstore(path, openertype)
--- a/tests/test-hybridencode.py	Mon Sep 17 15:13:17 2012 -0500
+++ b/tests/test-hybridencode.py	Tue Sep 18 15:30:22 2012 +0200
@@ -1,7 +1,6 @@
 from mercurial import store
 
-auxencode = lambda f: store._auxencode(f, True)
-hybridencode = lambda f: store._hybridencode(f, auxencode)
+hybridencode = lambda f: store._hybridencode(f, True)
 
 enc = hybridencode # used for 'dotencode' repo format
 
@@ -41,7 +40,7 @@
            ', pipe |, question-mark ?, asterisk *')
 
 print "encoding directories ending in .hg, .i or .d with '.hg' suffix"
-show('data/x.hg/x.i/x.d/foo')
+show('data/x.h.i/x.hg/x.i/x.d/foo')
 show('data/a.hg/a.i/a.d/foo')
 show('data/au.hg/au.i/au.d/foo')
 show('data/aux.hg/aux.i/aux.d/foo')
--- a/tests/test-hybridencode.py.out	Mon Sep 17 15:13:17 2012 -0500
+++ b/tests/test-hybridencode.py.out	Tue Sep 18 15:30:22 2012 +0200
@@ -35,8 +35,8 @@
 B = 'data/less ~3c, greater ~3e, colon ~3a, double-quote ~22, backslash ~5c, pipe ~7c, question-mark ~3f, asterisk ~2a'
 
 encoding directories ending in .hg, .i or .d with '.hg' suffix
-A = 'data/x.hg/x.i/x.d/foo'
-B = 'data/x.hg.hg/x.i.hg/x.d.hg/foo'
+A = 'data/x.h.i/x.hg/x.i/x.d/foo'
+B = 'data/x.h.i.hg/x.hg.hg/x.i.hg/x.d.hg/foo'
 
 A = 'data/a.hg/a.i/a.d/foo'
 B = 'data/a.hg.hg/a.i.hg/a.d.hg/foo'