equal
deleted
inserted
replaced
69 lowerencode = _build_lower_encodefun() |
69 lowerencode = _build_lower_encodefun() |
70 |
70 |
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: |
78 base = n.split('.')[0] |
78 base = n.split('.')[0] |
79 if base and (base in _windows_reserved_filenames): |
79 if base and (base in _windows_reserved_filenames): |
81 ec = "~%02x" % ord(n[2]) |
81 ec = "~%02x" % ord(n[2]) |
82 n = n[0:2] + ec + n[3:] |
82 n = n[0:2] + ec + n[3:] |
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. |
96 |
98 |
97 Default encoding (reversible): |
99 Default encoding (reversible): |
280 if self.entries is None: |
282 if self.entries is None: |
281 self._load() |
283 self._load() |
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) |
289 op = opener(self.path) |
292 op = opener(self.path) |
290 op.createmode = self.createmode |
293 op.createmode = self.createmode |
292 self.fncache = fnc |
295 self.fncache = fnc |
293 |
296 |
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 |
305 existing = [] |
308 existing = [] |
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 |
313 existing.append(f) |
316 existing.append(f) |
314 except OSError: |
317 except OSError: |
326 |
329 |
327 def store(requirements, path, opener, pathjoiner=None): |
330 def store(requirements, path, opener, pathjoiner=None): |
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) |