mercurial/store.py
changeset 12687 34d8247a4595
parent 12171 cc39d07d2212
child 13169 4c1fbed00224
equal deleted inserted replaced
12686:fe31f834a9ff 12687:34d8247a4595
    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)