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