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