##// END OF EJS Templates
store: simplify walking...
Matt Mackall -
r6899:56a7a54e default
parent child Browse files
Show More
@@ -1,125 +1,117 b''
1 1 # store.py - repository store handling for Mercurial
2 2 #
3 3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from i18n import _
9 9 import os, stat, osutil, util
10 10
11 11 def _buildencodefun():
12 12 e = '_'
13 13 win_reserved = [ord(x) for x in '\\:*?"<>|']
14 14 cmap = dict([ (chr(x), chr(x)) for x in xrange(127) ])
15 15 for x in (range(32) + range(126, 256) + win_reserved):
16 16 cmap[chr(x)] = "~%02x" % x
17 17 for x in range(ord("A"), ord("Z")+1) + [ord(e)]:
18 18 cmap[chr(x)] = e + chr(x).lower()
19 19 dmap = {}
20 20 for k, v in cmap.iteritems():
21 21 dmap[v] = k
22 22 def decode(s):
23 23 i = 0
24 24 while i < len(s):
25 25 for l in xrange(1, 4):
26 26 try:
27 27 yield dmap[s[i:i+l]]
28 28 i += l
29 29 break
30 30 except KeyError:
31 31 pass
32 32 else:
33 33 raise KeyError
34 34 return (lambda s: "".join([cmap[c] for c in s]),
35 35 lambda s: "".join(list(decode(s))))
36 36
37 37 encodefilename, decodefilename = _buildencodefun()
38 38
39 def _dirwalk(path, recurse):
40 '''yields (filename, size)'''
41 for e, kind, st in osutil.listdir(path, stat=True):
42 pe = os.path.join(path, e)
43 if kind == stat.S_IFDIR:
44 if recurse:
45 for x in _dirwalk(pe, True):
46 yield x
47 elif kind == stat.S_IFREG:
48 yield pe, st.st_size
49
50 39 def _calcmode(path):
51 40 try:
52 41 # files in .hg/ will be created using this mode
53 42 mode = os.stat(path).st_mode
54 43 # avoid some useless chmods
55 44 if (0777 & ~util._umask) == (0777 & mode):
56 45 mode = None
57 46 except OSError:
58 47 mode = None
59 48 return mode
60 49
61 50 class basicstore:
62 51 '''base class for local repository stores'''
63 52 def __init__(self, path, opener):
64 53 self.path = path
65 54 self.createmode = _calcmode(path)
66 55 self.opener = opener(self.path)
67 56 self.opener.createmode = self.createmode
68 57
69 58 def join(self, f):
70 59 return os.path.join(self.path, f)
71 60
72 def _revlogfiles(self, relpath='', recurse=False):
61 def _walk(self, relpath, recurse):
73 62 '''yields (filename, size)'''
74 if relpath:
75 path = os.path.join(self.path, relpath)
76 else:
77 path = self.path
78 if not os.path.isdir(path):
79 return
63 path = os.path.join(self.path, relpath)
80 64 striplen = len(self.path) + len(os.sep)
81 filetypes = ('.d', '.i')
82 for f, size in _dirwalk(path, recurse):
83 if (len(f) > 2) and f[-2:] in filetypes:
84 yield util.pconvert(f[striplen:]), size
65 prefix = path[striplen:]
66 l = []
67 if os.path.isdir(path):
68 visit = [path]
69 while visit:
70 p = visit.pop()
71 for f, kind, st in osutil.listdir(p, stat=True):
72 fp = os.path.join(p, f)
73 if kind == stat.S_IFREG and f[-2:] in ('.d', '.i'):
74 l.append((util.pconvert(fp[striplen:]), st.st_size))
75 elif kind == stat.S_IFDIR and recurse:
76 visit.append(fp)
77 return util.sort(l)
85 78
86 79 def datafiles(self, reporterror=None):
87 for x in self._revlogfiles('data', True):
88 yield x
80 return self._walk('data', True)
89 81
90 82 def walk(self):
91 83 '''yields (direncoded filename, size)'''
92 84 # yield data files first
93 85 for x in self.datafiles():
94 86 yield x
95 87 # yield manifest before changelog
96 meta = util.sort(self._revlogfiles())
88 meta = self._walk('', False)
97 89 meta.reverse()
98 90 for x in meta:
99 91 yield x
100 92
101 93 class encodedstore(basicstore):
102 94 def __init__(self, path, opener):
103 95 self.path = os.path.join(path, 'store')
104 96 self.createmode = _calcmode(self.path)
105 97 self.encodefn = encodefilename
106 98 op = opener(self.path)
107 99 op.createmode = self.createmode
108 100 self.opener = lambda f, *args, **kw: op(self.encodefn(f), *args, **kw)
109 101
110 102 def datafiles(self, reporterror=None):
111 for f, size in self._revlogfiles('data', True):
103 for f, size in self._walk('data', True):
112 104 try:
113 105 yield decodefilename(f), size
114 106 except KeyError:
115 107 if not reporterror:
116 108 raise
117 109 reporterror(_("cannot decode filename '%s'") % f)
118 110
119 111 def join(self, f):
120 112 return os.path.join(self.path, self.encodefn(f))
121 113
122 114 def store(requirements, path, opener):
123 115 if 'store' in requirements:
124 116 return encodedstore(path, opener)
125 117 return basicstore(path, opener)
General Comments 0
You need to be logged in to leave comments. Login now