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