##// END OF EJS Templates
index: rename _fix_index() since it no longer fixes the index...
Martin von Zweigbergk -
r39251:5961517f default
parent child Browse files
Show More
@@ -1,176 +1,177
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 def _fix_index(self, i):
47 def _check_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):
51 51 raise IndexError
52 return i
53 52
54 53 def __getitem__(self, i):
55 54 if i == -1:
56 55 return (0, 0, 0, -1, -1, -1, -1, nullid)
57 i = self._fix_index(i)
56 self._check_index(i)
58 57 if i >= self._lgt:
59 58 return self._extra[i - self._lgt]
60 59 index = self._calculate_index(i)
61 60 r = struct.unpack(indexformatng, self._data[index:index + indexsize])
62 61 if i == 0:
63 62 e = list(r)
64 63 type = gettype(e[0])
65 64 e[0] = offset_type(0, type)
66 65 return tuple(e)
67 66 return r
68 67
69 68 class IndexObject(BaseIndexObject):
70 69 def __init__(self, data):
71 70 assert len(data) % indexsize == 0
72 71 self._data = data
73 72 self._lgt = len(data) // indexsize
74 73 self._extra = []
75 74
76 75 def _calculate_index(self, i):
77 76 return i * indexsize
78 77
79 78 def __delitem__(self, i):
80 79 if not isinstance(i, slice) or not i.stop == -1 or i.step is not None:
81 80 raise ValueError("deleting slices only supports a:-1 with step 1")
82 i = self._fix_index(i.start)
81 i = i.start
82 self._check_index(i)
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 i = self._fix_index(i.start)
116 i = i.start
117 self._check_index(i)
117 118 if i < self._lgt:
118 119 self._offsets = self._offsets[:i]
119 120 self._lgt = i
120 121 self._extra = []
121 122 else:
122 123 self._extra = self._extra[:i - self._lgt]
123 124
124 125 def _calculate_index(self, i):
125 126 return self._offsets[i]
126 127
127 128 def parse_index2(data, inline):
128 129 if not inline:
129 130 return IndexObject(data), None
130 131 return InlinedIndexObject(data, inline), (0, data)
131 132
132 133 def parse_dirstate(dmap, copymap, st):
133 134 parents = [st[:20], st[20: 40]]
134 135 # dereference fields so they will be local in loop
135 136 format = ">cllll"
136 137 e_size = struct.calcsize(format)
137 138 pos1 = 40
138 139 l = len(st)
139 140
140 141 # the inner loop
141 142 while pos1 < l:
142 143 pos2 = pos1 + e_size
143 144 e = _unpack(">cllll", st[pos1:pos2]) # a literal here is faster
144 145 pos1 = pos2 + e[4]
145 146 f = st[pos2:pos1]
146 147 if '\0' in f:
147 148 f, c = f.split('\0')
148 149 copymap[f] = c
149 150 dmap[f] = e[:4]
150 151 return parents
151 152
152 153 def pack_dirstate(dmap, copymap, pl, now):
153 154 now = int(now)
154 155 cs = stringio()
155 156 write = cs.write
156 157 write("".join(pl))
157 158 for f, e in dmap.iteritems():
158 159 if e[0] == 'n' and e[3] == now:
159 160 # The file was last modified "simultaneously" with the current
160 161 # write to dirstate (i.e. within the same second for file-
161 162 # systems with a granularity of 1 sec). This commonly happens
162 163 # for at least a couple of files on 'update'.
163 164 # The user could change the file without changing its size
164 165 # within the same second. Invalidate the file's mtime in
165 166 # dirstate, forcing future 'status' calls to compare the
166 167 # contents of the file if the size is the same. This prevents
167 168 # mistakenly treating such files as clean.
168 169 e = dirstatetuple(e[0], e[1], e[2], -1)
169 170 dmap[f] = e
170 171
171 172 if f in copymap:
172 173 f = "%s\0%s" % (f, copymap[f])
173 174 e = _pack(">cllll", e[0], e[1], e[2], e[3], len(f))
174 175 write(e)
175 176 write(f)
176 177 return cs.getvalue()
General Comments 0
You need to be logged in to leave comments. Login now