##// END OF EJS Templates
store: encode first period or space in filenames (issue1713)...
Adrian Buehlmann -
r12687:34d8247a default
parent child Browse files
Show More
@@ -22,7 +22,8 b' propertycache = util.propertycache'
22 class localrepository(repo.repository):
22 class localrepository(repo.repository):
23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey'))
23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey'))
24 supportedformats = set(('revlogv1', 'parentdelta'))
24 supportedformats = set(('revlogv1', 'parentdelta'))
25 supported = supportedformats | set(('store', 'fncache', 'shared'))
25 supported = supportedformats | set(('store', 'fncache', 'shared',
26 'dotencode'))
26
27
27 def __init__(self, baseui, path=None, create=0):
28 def __init__(self, baseui, path=None, create=0):
28 repo.repository.__init__(self)
29 repo.repository.__init__(self)
@@ -52,6 +53,8 b' class localrepository(repo.repository):'
52 requirements.append("store")
53 requirements.append("store")
53 if self.ui.configbool('format', 'usefncache', True):
54 if self.ui.configbool('format', 'usefncache', True):
54 requirements.append("fncache")
55 requirements.append("fncache")
56 if self.ui.configbool('format', 'dotencode', True):
57 requirements.append('dotencode')
55 # create an invalid changelog
58 # create an invalid changelog
56 self.opener("00changelog.i", "a").write(
59 self.opener("00changelog.i", "a").write(
57 '\0\0\0\2' # represents revlogv2
60 '\0\0\0\2' # represents revlogv2
@@ -71,7 +71,7 b' lowerencode = _build_lower_encodefun()'
71 _windows_reserved_filenames = '''con prn aux nul
71 _windows_reserved_filenames = '''con prn aux nul
72 com1 com2 com3 com4 com5 com6 com7 com8 com9
72 com1 com2 com3 com4 com5 com6 com7 com8 com9
73 lpt1 lpt2 lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9'''.split()
73 lpt1 lpt2 lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9'''.split()
74 def auxencode(path):
74 def _auxencode(path, dotencode):
75 res = []
75 res = []
76 for n in path.split('/'):
76 for n in path.split('/'):
77 if n:
77 if n:
@@ -83,13 +83,15 b' def auxencode(path):'
83 if n[-1] in '. ':
83 if n[-1] in '. ':
84 # encode last period or space ('foo...' -> 'foo..~2e')
84 # encode last period or space ('foo...' -> 'foo..~2e')
85 n = n[:-1] + "~%02x" % ord(n[-1])
85 n = n[:-1] + "~%02x" % ord(n[-1])
86 if dotencode and n[0] in '. ':
87 n = "~%02x" % ord(n[0]) + n[1:]
86 res.append(n)
88 res.append(n)
87 return '/'.join(res)
89 return '/'.join(res)
88
90
89 MAX_PATH_LEN_IN_HGSTORE = 120
91 MAX_PATH_LEN_IN_HGSTORE = 120
90 DIR_PREFIX_LEN = 8
92 DIR_PREFIX_LEN = 8
91 _MAX_SHORTENED_DIRS_LEN = 8 * (DIR_PREFIX_LEN + 1) - 4
93 _MAX_SHORTENED_DIRS_LEN = 8 * (DIR_PREFIX_LEN + 1) - 4
92 def hybridencode(path):
94 def _hybridencode(path, auxencode):
93 '''encodes path with a length limit
95 '''encodes path with a length limit
94
96
95 Encodes all paths that begin with 'data/', according to the following.
97 Encodes all paths that begin with 'data/', according to the following.
@@ -282,7 +284,8 b' class fncache(object):'
282 return iter(self.entries)
284 return iter(self.entries)
283
285
284 class fncachestore(basicstore):
286 class fncachestore(basicstore):
285 def __init__(self, path, opener, pathjoiner):
287 def __init__(self, path, opener, pathjoiner, encode):
288 self.encode = encode
286 self.pathjoiner = pathjoiner
289 self.pathjoiner = pathjoiner
287 self.path = self.pathjoiner(path, 'store')
290 self.path = self.pathjoiner(path, 'store')
288 self.createmode = _calcmode(self.path)
291 self.createmode = _calcmode(self.path)
@@ -294,11 +297,11 b' class fncachestore(basicstore):'
294 def fncacheopener(path, mode='r', *args, **kw):
297 def fncacheopener(path, mode='r', *args, **kw):
295 if mode not in ('r', 'rb') and path.startswith('data/'):
298 if mode not in ('r', 'rb') and path.startswith('data/'):
296 fnc.add(path)
299 fnc.add(path)
297 return op(hybridencode(path), mode, *args, **kw)
300 return op(self.encode(path), mode, *args, **kw)
298 self.opener = fncacheopener
301 self.opener = fncacheopener
299
302
300 def join(self, f):
303 def join(self, f):
301 return self.pathjoiner(self.path, hybridencode(f))
304 return self.pathjoiner(self.path, self.encode(f))
302
305
303 def datafiles(self):
306 def datafiles(self):
304 rewrite = False
307 rewrite = False
@@ -306,7 +309,7 b' class fncachestore(basicstore):'
306 pjoin = self.pathjoiner
309 pjoin = self.pathjoiner
307 spath = self.path
310 spath = self.path
308 for f in self.fncache:
311 for f in self.fncache:
309 ef = hybridencode(f)
312 ef = self.encode(f)
310 try:
313 try:
311 st = os.stat(pjoin(spath, ef))
314 st = os.stat(pjoin(spath, ef))
312 yield f, ef, st.st_size
315 yield f, ef, st.st_size
@@ -328,6 +331,8 b' def store(requirements, path, opener, pa'
328 pathjoiner = pathjoiner or os.path.join
331 pathjoiner = pathjoiner or os.path.join
329 if 'store' in requirements:
332 if 'store' in requirements:
330 if 'fncache' in requirements:
333 if 'fncache' in requirements:
331 return fncachestore(path, opener, pathjoiner)
334 auxencode = lambda f: _auxencode(f, 'dotencode' in requirements)
335 encode = lambda f: _hybridencode(f, auxencode)
336 return fncachestore(path, opener, pathjoiner, encode)
332 return encodedstore(path, opener, pathjoiner)
337 return encodedstore(path, opener, pathjoiner)
333 return basicstore(path, opener, pathjoiner)
338 return basicstore(path, opener, pathjoiner)
@@ -2,7 +2,10 b''
2
2
3 from mercurial import store
3 from mercurial import store
4
4
5 enc = store.hybridencode # used for fncache repo format
5 auxencode = lambda f: store._auxencode(f, True)
6 hybridencode = lambda f: store._hybridencode(f, auxencode)
7
8 enc = hybridencode # used for 'dotencode' repo format
6
9
7 def show(s):
10 def show(s):
8 print "A = '%s'" % s
11 print "A = '%s'" % s
@@ -22,4 +25,5 b" show('data/Project Planning/Resources/An"
22 'Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt')
25 'Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt')
23 show('data/Project.Planning/Resources/AnotherLongDirectoryName/'
26 show('data/Project.Planning/Resources/AnotherLongDirectoryName/'
24 'Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt')
27 'Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt')
25 show('data/foo.../foo / /a./_. /__/.x../ bla/something.i')
28 show('data/foo.../foo / /a./_. /__/.x../ bla/.FOO/something.i')
29
@@ -16,6 +16,6 b" B = 'dh/project_/resource/anotherl/follo"
16 A = 'data/Project.Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt'
16 A = 'data/Project.Planning/Resources/AnotherLongDirectoryName/Followedbyanother/AndAnother/AndThenAnExtremelyLongFileName.txt'
17 B = 'dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilena0fd7c506f5c9d58204444fc67e9499006bd2d445.txt'
17 B = 'dh/project_/resource/anotherl/followed/andanoth/andthenanextremelylongfilena0fd7c506f5c9d58204444fc67e9499006bd2d445.txt'
18
18
19 A = 'data/foo.../foo / /a./_. /__/.x../ bla/something.i'
19 A = 'data/foo.../foo / /a./_. /__/.x../ bla/.FOO/something.i'
20 B = 'data/foo..~2e/foo ~20/~20/a~2e/__.~20/____/.x.~2e/ bla/something.i'
20 B = 'data/foo..~2e/foo ~20/~20/a~2e/__.~20/____/~2ex.~2e/~20 bla/~2e_f_o_o/something.i'
21
21
@@ -42,6 +42,7 b" creating 'local'"
42 revlogv1
42 revlogv1
43 store
43 store
44 fncache
44 fncache
45 dotencode
45 $ echo this > local/foo
46 $ echo this > local/foo
46 $ hg ci --cwd local -A -m "init"
47 $ hg ci --cwd local -A -m "init"
47 adding foo
48 adding foo
@@ -157,6 +158,7 b" creating 'local/sub/repo'"
157 revlogv1
158 revlogv1
158 store
159 store
159 fncache
160 fncache
161 dotencode
160
162
161 prepare test of init of url configured from paths
163 prepare test of init of url configured from paths
162
164
@@ -173,6 +175,7 b' init should (for consistency with clone)'
173 revlogv1
175 revlogv1
174 store
176 store
175 fncache
177 fncache
178 dotencode
176
179
177 verify that clone also expand urls
180 verify that clone also expand urls
178
181
@@ -185,3 +188,4 b' verify that clone also expand urls'
185 revlogv1
188 revlogv1
186 store
189 store
187 fncache
190 fncache
191 dotencode
General Comments 0
You need to be logged in to leave comments. Login now