##// END OF EJS Templates
parsers: adjust pure-python version to mimic a3dacabd476b...
Augie Fackler -
r39082:a1f93457 default
parent child Browse files
Show More
@@ -1,176 +1,176 b''
1 # parsers.py - Python implementation of parsers.c
1 # parsers.py - Python implementation of parsers.c
2 #
2 #
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import struct
10 import struct
11 import zlib
11 import zlib
12
12
13 from ..node import nullid
13 from ..node import nullid
14 from .. import pycompat
14 from .. import pycompat
15 stringio = pycompat.bytesio
15 stringio = pycompat.bytesio
16
16
17
17
18 _pack = struct.pack
18 _pack = struct.pack
19 _unpack = struct.unpack
19 _unpack = struct.unpack
20 _compress = zlib.compress
20 _compress = zlib.compress
21 _decompress = zlib.decompress
21 _decompress = zlib.decompress
22
22
23 # Some code below makes tuples directly because it's more convenient. However,
23 # Some code below makes tuples directly because it's more convenient. However,
24 # code outside this module should always use dirstatetuple.
24 # code outside this module should always use dirstatetuple.
25 def dirstatetuple(*x):
25 def dirstatetuple(*x):
26 # x is a tuple
26 # x is a tuple
27 return x
27 return x
28
28
29 indexformatng = ">Qiiiiii20s12x"
29 indexformatng = ">Qiiiiii20s12x"
30 indexfirst = struct.calcsize('Q')
30 indexfirst = struct.calcsize('Q')
31 sizeint = struct.calcsize('i')
31 sizeint = struct.calcsize('i')
32 indexsize = struct.calcsize(indexformatng)
32 indexsize = struct.calcsize(indexformatng)
33
33
34 def gettype(q):
34 def gettype(q):
35 return int(q & 0xFFFF)
35 return int(q & 0xFFFF)
36
36
37 def offset_type(offset, type):
37 def offset_type(offset, type):
38 return int(int(offset) << 16 | type)
38 return int(int(offset) << 16 | type)
39
39
40 class BaseIndexObject(object):
40 class BaseIndexObject(object):
41 def __len__(self):
41 def __len__(self):
42 return self._lgt + len(self._extra)
42 return self._lgt + len(self._extra)
43
43
44 def append(self, tup):
44 def append(self, tup):
45 self._extra.append(tup)
45 self._extra.append(tup)
46
46
47 def _fix_index(self, i):
47 def _fix_index(self, i):
48 if not isinstance(i, int):
48 if not isinstance(i, int):
49 raise TypeError("expecting int indexes")
49 raise TypeError("expecting int indexes")
50 if i < 0 or i >= len(self) + 1:
50 if i < 0 or i >= len(self) + 1:
51 raise IndexError
51 raise IndexError
52 return i
52 return i
53
53
54 def __getitem__(self, i):
54 def __getitem__(self, i):
55 if i == -1 or i == len(self):
55 if i == -1:
56 return (0, 0, 0, -1, -1, -1, -1, nullid)
56 return (0, 0, 0, -1, -1, -1, -1, nullid)
57 i = self._fix_index(i)
57 i = self._fix_index(i)
58 if i >= self._lgt:
58 if i >= self._lgt:
59 return self._extra[i - self._lgt]
59 return self._extra[i - self._lgt]
60 index = self._calculate_index(i)
60 index = self._calculate_index(i)
61 r = struct.unpack(indexformatng, self._data[index:index + indexsize])
61 r = struct.unpack(indexformatng, self._data[index:index + indexsize])
62 if i == 0:
62 if i == 0:
63 e = list(r)
63 e = list(r)
64 type = gettype(e[0])
64 type = gettype(e[0])
65 e[0] = offset_type(0, type)
65 e[0] = offset_type(0, type)
66 return tuple(e)
66 return tuple(e)
67 return r
67 return r
68
68
69 class IndexObject(BaseIndexObject):
69 class IndexObject(BaseIndexObject):
70 def __init__(self, data):
70 def __init__(self, data):
71 assert len(data) % indexsize == 0
71 assert len(data) % indexsize == 0
72 self._data = data
72 self._data = data
73 self._lgt = len(data) // indexsize
73 self._lgt = len(data) // indexsize
74 self._extra = []
74 self._extra = []
75
75
76 def _calculate_index(self, i):
76 def _calculate_index(self, i):
77 return i * indexsize
77 return i * indexsize
78
78
79 def __delitem__(self, i):
79 def __delitem__(self, i):
80 if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
80 if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
81 raise ValueError("deleting slices only supports a:-1 with step 1")
81 raise ValueError("deleting slices only supports a:-1 with step 1")
82 i = self._fix_index(i.start)
82 i = self._fix_index(i.start)
83 if i < self._lgt:
83 if i < self._lgt:
84 self._data = self._data[:i * indexsize]
84 self._data = self._data[:i * indexsize]
85 self._lgt = i
85 self._lgt = i
86 self._extra = []
86 self._extra = []
87 else:
87 else:
88 self._extra = self._extra[:i - self._lgt]
88 self._extra = self._extra[:i - self._lgt]
89
89
90 class InlinedIndexObject(BaseIndexObject):
90 class InlinedIndexObject(BaseIndexObject):
91 def __init__(self, data, inline=0):
91 def __init__(self, data, inline=0):
92 self._data = data
92 self._data = data
93 self._lgt = self._inline_scan(None)
93 self._lgt = self._inline_scan(None)
94 self._inline_scan(self._lgt)
94 self._inline_scan(self._lgt)
95 self._extra = []
95 self._extra = []
96
96
97 def _inline_scan(self, lgt):
97 def _inline_scan(self, lgt):
98 off = 0
98 off = 0
99 if lgt is not None:
99 if lgt is not None:
100 self._offsets = [0] * lgt
100 self._offsets = [0] * lgt
101 count = 0
101 count = 0
102 while off <= len(self._data) - indexsize:
102 while off <= len(self._data) - indexsize:
103 s, = struct.unpack('>i',
103 s, = struct.unpack('>i',
104 self._data[off + indexfirst:off + sizeint + indexfirst])
104 self._data[off + indexfirst:off + sizeint + indexfirst])
105 if lgt is not None:
105 if lgt is not None:
106 self._offsets[count] = off
106 self._offsets[count] = off
107 count += 1
107 count += 1
108 off += indexsize + s
108 off += indexsize + s
109 if off != len(self._data):
109 if off != len(self._data):
110 raise ValueError("corrupted data")
110 raise ValueError("corrupted data")
111 return count
111 return count
112
112
113 def __delitem__(self, i):
113 def __delitem__(self, i):
114 if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
114 if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
115 raise ValueError("deleting slices only supports a:-1 with step 1")
115 raise ValueError("deleting slices only supports a:-1 with step 1")
116 i = self._fix_index(i.start)
116 i = self._fix_index(i.start)
117 if i < self._lgt:
117 if i < self._lgt:
118 self._offsets = self._offsets[:i]
118 self._offsets = self._offsets[:i]
119 self._lgt = i
119 self._lgt = i
120 self._extra = []
120 self._extra = []
121 else:
121 else:
122 self._extra = self._extra[:i - self._lgt]
122 self._extra = self._extra[:i - self._lgt]
123
123
124 def _calculate_index(self, i):
124 def _calculate_index(self, i):
125 return self._offsets[i]
125 return self._offsets[i]
126
126
127 def parse_index2(data, inline):
127 def parse_index2(data, inline):
128 if not inline:
128 if not inline:
129 return IndexObject(data), None
129 return IndexObject(data), None
130 return InlinedIndexObject(data, inline), (0, data)
130 return InlinedIndexObject(data, inline), (0, data)
131
131
132 def parse_dirstate(dmap, copymap, st):
132 def parse_dirstate(dmap, copymap, st):
133 parents = [st[:20], st[20: 40]]
133 parents = [st[:20], st[20: 40]]
134 # dereference fields so they will be local in loop
134 # dereference fields so they will be local in loop
135 format = ">cllll"
135 format = ">cllll"
136 e_size = struct.calcsize(format)
136 e_size = struct.calcsize(format)
137 pos1 = 40
137 pos1 = 40
138 l = len(st)
138 l = len(st)
139
139
140 # the inner loop
140 # the inner loop
141 while pos1 < l:
141 while pos1 < l:
142 pos2 = pos1 + e_size
142 pos2 = pos1 + e_size
143 e = _unpack(">cllll", st[pos1:pos2]) # a literal here is faster
143 e = _unpack(">cllll", st[pos1:pos2]) # a literal here is faster
144 pos1 = pos2 + e[4]
144 pos1 = pos2 + e[4]
145 f = st[pos2:pos1]
145 f = st[pos2:pos1]
146 if '\0' in f:
146 if '\0' in f:
147 f, c = f.split('\0')
147 f, c = f.split('\0')
148 copymap[f] = c
148 copymap[f] = c
149 dmap[f] = e[:4]
149 dmap[f] = e[:4]
150 return parents
150 return parents
151
151
152 def pack_dirstate(dmap, copymap, pl, now):
152 def pack_dirstate(dmap, copymap, pl, now):
153 now = int(now)
153 now = int(now)
154 cs = stringio()
154 cs = stringio()
155 write = cs.write
155 write = cs.write
156 write("".join(pl))
156 write("".join(pl))
157 for f, e in dmap.iteritems():
157 for f, e in dmap.iteritems():
158 if e[0] == 'n' and e[3] == now:
158 if e[0] == 'n' and e[3] == now:
159 # The file was last modified "simultaneously" with the current
159 # The file was last modified "simultaneously" with the current
160 # write to dirstate (i.e. within the same second for file-
160 # write to dirstate (i.e. within the same second for file-
161 # systems with a granularity of 1 sec). This commonly happens
161 # systems with a granularity of 1 sec). This commonly happens
162 # for at least a couple of files on 'update'.
162 # for at least a couple of files on 'update'.
163 # The user could change the file without changing its size
163 # The user could change the file without changing its size
164 # within the same second. Invalidate the file's mtime in
164 # within the same second. Invalidate the file's mtime in
165 # dirstate, forcing future 'status' calls to compare the
165 # dirstate, forcing future 'status' calls to compare the
166 # contents of the file if the size is the same. This prevents
166 # contents of the file if the size is the same. This prevents
167 # mistakenly treating such files as clean.
167 # mistakenly treating such files as clean.
168 e = dirstatetuple(e[0], e[1], e[2], -1)
168 e = dirstatetuple(e[0], e[1], e[2], -1)
169 dmap[f] = e
169 dmap[f] = e
170
170
171 if f in copymap:
171 if f in copymap:
172 f = "%s\0%s" % (f, copymap[f])
172 f = "%s\0%s" % (f, copymap[f])
173 e = _pack(">cllll", e[0], e[1], e[2], e[3], len(f))
173 e = _pack(">cllll", e[0], e[1], e[2], e[3], len(f))
174 write(e)
174 write(e)
175 write(f)
175 write(f)
176 return cs.getvalue()
176 return cs.getvalue()
General Comments 0
You need to be logged in to leave comments. Login now