Mercurial > public > mercurial-scm > hg-stable
diff mercurial/store.py @ 8531:810387f59696
filelog encoding: move the encoding/decoding into store
the escaping of directories ending with .i or .d doesn't
really belong to filelog.
we put the encoding/decoding in store instead, for backwards
compat, streamclone and the fncache file format still uses the
partially encoded filenames.
author | Benoit Boissinot <benoit.boissinot@ens-lyon.org> |
---|---|
date | Wed, 20 May 2009 18:35:47 +0200 |
parents | 03196ac9a8b9 |
children | c31fe74a6633 |
line wrap: on
line diff
--- a/mercurial/store.py Wed May 20 18:35:41 2009 +0200 +++ b/mercurial/store.py Wed May 20 18:35:47 2009 +0200 @@ -11,6 +11,24 @@ _sha = util.sha1 +# This avoids a collision between a file named foo and a dir named +# foo.i or foo.d +def encodedir(path): + if not path.startswith('data/'): + return path + return (path + .replace(".hg/", ".hg.hg/") + .replace(".i/", ".i.hg/") + .replace(".d/", ".d.hg/")) + +def decodedir(path): + if not path.startswith('data/'): + return path + return (path + .replace(".d.hg/", ".d/") + .replace(".i.hg/", ".i/") + .replace(".hg.hg/", ".hg/")) + def _buildencodefun(): e = '_' win_reserved = [ord(x) for x in '\\:*?"<>|'] @@ -34,8 +52,8 @@ pass else: raise KeyError - return (lambda s: "".join([cmap[c] for c in s]), - lambda s: "".join(list(decode(s)))) + return (lambda s: "".join([cmap[c] for c in encodedir(s)]), + lambda s: decodedir("".join(list(decode(s))))) encodefilename, decodefilename = _buildencodefun() @@ -104,6 +122,8 @@ ''' if not path.startswith('data/'): return path + # escape directories ending with .i and .d + path = encodedir(path) ndpath = path[len('data/'):] res = 'data/' + auxencode(encodefilename(ndpath)) if len(res) > MAX_PATH_LEN_IN_HGSTORE: @@ -155,7 +175,7 @@ self.opener.createmode = self.createmode def join(self, f): - return self.pathjoiner(self.path, f) + return self.pathjoiner(self.path, encodedir(f)) def _walk(self, relpath, recurse): '''yields (unencoded, encoded, size)''' @@ -170,7 +190,7 @@ fp = self.pathjoiner(p, f) if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'): n = util.pconvert(fp[striplen:]) - l.append((n, n, st.st_size)) + l.append((decodedir(n), n, st.st_size)) elif kind == stat.S_IFDIR and recurse: visit.append(fp) return sorted(l) @@ -215,6 +235,8 @@ [self.pathjoiner('store', f) for f in _data.split()]) class fncache(object): + # the filename used to be partially encoded + # hence the encodedir/decodedir dance def __init__(self, opener): self.opener = opener self.entries = None @@ -231,20 +253,20 @@ if (len(line) < 2) or (line[-1] != '\n'): t = _('invalid entry in fncache, line %s') % (n + 1) raise util.Abort(t) - self.entries.add(line[:-1]) + self.entries.add(decodedir(line[:-1])) fp.close() def rewrite(self, files): fp = self.opener('fncache', mode='wb') for p in files: - fp.write(p + '\n') + fp.write(encodedir(p) + '\n') fp.close() self.entries = set(files) def add(self, fn): if self.entries is None: self._load() - self.opener('fncache', 'ab').write(fn + '\n') + self.opener('fncache', 'ab').write(encodedir(fn) + '\n') def __contains__(self, fn): if self.entries is None: