[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