##// END OF EJS Templates
store: simplify class hierarchy
Matt Mackall -
r6898:69aeaaaf default
parent child Browse files
Show More
@@ -1,126 +1,125 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 39 def _dirwalk(path, recurse):
40 40 '''yields (filename, size)'''
41 41 for e, kind, st in osutil.listdir(path, stat=True):
42 42 pe = os.path.join(path, e)
43 43 if kind == stat.S_IFDIR:
44 44 if recurse:
45 45 for x in _dirwalk(pe, True):
46 46 yield x
47 47 elif kind == stat.S_IFREG:
48 48 yield pe, st.st_size
49 49
50 class _store:
50 def _calcmode(path):
51 try:
52 # files in .hg/ will be created using this mode
53 mode = os.stat(path).st_mode
54 # avoid some useless chmods
55 if (0777 & ~util._umask) == (0777 & mode):
56 mode = None
57 except OSError:
58 mode = None
59 return mode
60
61 class basicstore:
51 62 '''base class for local repository stores'''
52 def __init__(self, path):
63 def __init__(self, path, opener):
53 64 self.path = path
54 try:
55 # files in .hg/ will be created using this mode
56 mode = os.stat(self.path).st_mode
57 # avoid some useless chmods
58 if (0777 & ~util._umask) == (0777 & mode):
59 mode = None
60 except OSError:
61 mode = None
62 self.createmode = mode
65 self.createmode = _calcmode(path)
66 self.opener = opener(self.path)
67 self.opener.createmode = self.createmode
63 68
64 69 def join(self, f):
65 70 return os.path.join(self.path, f)
66 71
67 72 def _revlogfiles(self, relpath='', recurse=False):
68 73 '''yields (filename, size)'''
69 74 if relpath:
70 75 path = os.path.join(self.path, relpath)
71 76 else:
72 77 path = self.path
73 78 if not os.path.isdir(path):
74 79 return
75 80 striplen = len(self.path) + len(os.sep)
76 81 filetypes = ('.d', '.i')
77 82 for f, size in _dirwalk(path, recurse):
78 83 if (len(f) > 2) and f[-2:] in filetypes:
79 84 yield util.pconvert(f[striplen:]), size
80 85
81 86 def datafiles(self, reporterror=None):
82 87 for x in self._revlogfiles('data', True):
83 88 yield x
84 89
85 90 def walk(self):
86 91 '''yields (direncoded filename, size)'''
87 92 # yield data files first
88 93 for x in self.datafiles():
89 94 yield x
90 95 # yield manifest before changelog
91 96 meta = util.sort(self._revlogfiles())
92 97 meta.reverse()
93 98 for x in meta:
94 99 yield x
95 100
96 class directstore(_store):
101 class encodedstore(basicstore):
97 102 def __init__(self, path, opener):
98 _store.__init__(self, path)
99 self.opener = opener(self.path)
100 self.opener.createmode = self.createmode
101
102 class encodedstore(_store):
103 def __init__(self, path, opener):
104 _store.__init__(self, os.path.join(path, 'store'))
103 self.path = os.path.join(path, 'store')
104 self.createmode = _calcmode(self.path)
105 105 self.encodefn = encodefilename
106 106 op = opener(self.path)
107 107 op.createmode = self.createmode
108 108 self.opener = lambda f, *args, **kw: op(self.encodefn(f), *args, **kw)
109 109
110 110 def datafiles(self, reporterror=None):
111 111 for f, size in self._revlogfiles('data', True):
112 112 try:
113 113 yield decodefilename(f), size
114 114 except KeyError:
115 115 if not reporterror:
116 116 raise
117 117 reporterror(_("cannot decode filename '%s'") % f)
118 118
119 119 def join(self, f):
120 120 return os.path.join(self.path, self.encodefn(f))
121 121
122 122 def store(requirements, path, opener):
123 if 'store' not in requirements:
124 return directstore(path, opener)
125 else:
123 if 'store' in requirements:
126 124 return encodedstore(path, opener)
125 return basicstore(path, opener)
@@ -1,26 +1,26 b''
1 1 #!/bin/sh
2 2
3 3 echo % prepare repo
4 4 hg init
5 5 echo "some text" > FOO.txt
6 6 echo "another text" > bar.txt
7 7 echo "more text" > QUICK.txt
8 8 hg add
9 9 hg ci -d '0 0' -mtest1
10 10
11 11 echo
12 12 echo % verify
13 13 hg verify
14 14
15 15 echo
16 16 echo % introduce some bugs in repo
17 17 cd .hg/store/data
18 18 mv _f_o_o.txt.i X_f_o_o.txt.i
19 19 mv bar.txt.i xbar.txt.i
20 20 rm _q_u_i_c_k.txt.i
21 21
22 22 echo
23 23 echo % verify
24 24 hg verify
25 25
26 return 0
26 exit 0
General Comments 0
You need to be logged in to leave comments. Login now