Mercurial > public > mercurial-scm > hg
comparison mercurial/linelog.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | ee97f7a677f3 |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
21 from __future__ import absolute_import, print_function | 21 from __future__ import absolute_import, print_function |
22 | 22 |
23 import abc | 23 import abc |
24 import struct | 24 import struct |
25 | 25 |
26 from .thirdparty import ( | 26 from .thirdparty import attr |
27 attr, | 27 from . import pycompat |
28 ) | |
29 from . import ( | |
30 pycompat, | |
31 ) | |
32 | 28 |
33 _llentry = struct.Struct('>II') | 29 _llentry = struct.Struct('>II') |
30 | |
34 | 31 |
35 class LineLogError(Exception): | 32 class LineLogError(Exception): |
36 """Error raised when something bad happens internally in linelog.""" | 33 """Error raised when something bad happens internally in linelog.""" |
34 | |
37 | 35 |
38 @attr.s | 36 @attr.s |
39 class lineinfo(object): | 37 class lineinfo(object): |
40 # Introducing revision of this line. | 38 # Introducing revision of this line. |
41 rev = attr.ib() | 39 rev = attr.ib() |
42 # Line number for this line in its introducing revision. | 40 # Line number for this line in its introducing revision. |
43 linenum = attr.ib() | 41 linenum = attr.ib() |
44 # Private. Offset in the linelog program of this line. Used internally. | 42 # Private. Offset in the linelog program of this line. Used internally. |
45 _offset = attr.ib() | 43 _offset = attr.ib() |
46 | 44 |
45 | |
47 @attr.s | 46 @attr.s |
48 class annotateresult(object): | 47 class annotateresult(object): |
49 rev = attr.ib() | 48 rev = attr.ib() |
50 lines = attr.ib() | 49 lines = attr.ib() |
51 _eof = attr.ib() | 50 _eof = attr.ib() |
52 | 51 |
53 def __iter__(self): | 52 def __iter__(self): |
54 return iter(self.lines) | 53 return iter(self.lines) |
55 | 54 |
55 | |
56 class _llinstruction(object): | 56 class _llinstruction(object): |
57 | 57 |
58 __metaclass__ = abc.ABCMeta | 58 __metaclass__ = abc.ABCMeta |
59 | 59 |
60 @abc.abstractmethod | 60 @abc.abstractmethod |
88 Returns: | 88 Returns: |
89 The new value of pc. Returns None if exeuction should stop | 89 The new value of pc. Returns None if exeuction should stop |
90 (that is, we've found the end of the file.) | 90 (that is, we've found the end of the file.) |
91 """ | 91 """ |
92 | 92 |
93 | |
93 class _jge(_llinstruction): | 94 class _jge(_llinstruction): |
94 """If the current rev is greater than or equal to op1, jump to op2.""" | 95 """If the current rev is greater than or equal to op1, jump to op2.""" |
95 | 96 |
96 def __init__(self, op1, op2): | 97 def __init__(self, op1, op2): |
97 self._cmprev = op1 | 98 self._cmprev = op1 |
99 | 100 |
100 def __str__(self): | 101 def __str__(self): |
101 return r'JGE %d %d' % (self._cmprev, self._target) | 102 return r'JGE %d %d' % (self._cmprev, self._target) |
102 | 103 |
103 def __eq__(self, other): | 104 def __eq__(self, other): |
104 return (type(self) == type(other) | 105 return ( |
105 and self._cmprev == other._cmprev | 106 type(self) == type(other) |
106 and self._target == other._target) | 107 and self._cmprev == other._cmprev |
108 and self._target == other._target | |
109 ) | |
107 | 110 |
108 def encode(self): | 111 def encode(self): |
109 return _llentry.pack(self._cmprev << 2, self._target) | 112 return _llentry.pack(self._cmprev << 2, self._target) |
110 | 113 |
111 def execute(self, rev, pc, emit): | 114 def execute(self, rev, pc, emit): |
112 if rev >= self._cmprev: | 115 if rev >= self._cmprev: |
113 return self._target | 116 return self._target |
114 return pc + 1 | 117 return pc + 1 |
115 | 118 |
119 | |
116 class _jump(_llinstruction): | 120 class _jump(_llinstruction): |
117 """Unconditional jumps are expressed as a JGE with op1 set to 0.""" | 121 """Unconditional jumps are expressed as a JGE with op1 set to 0.""" |
118 | 122 |
119 def __init__(self, op1, op2): | 123 def __init__(self, op1, op2): |
120 if op1 != 0: | 124 if op1 != 0: |
123 | 127 |
124 def __str__(self): | 128 def __str__(self): |
125 return r'JUMP %d' % (self._target) | 129 return r'JUMP %d' % (self._target) |
126 | 130 |
127 def __eq__(self, other): | 131 def __eq__(self, other): |
128 return (type(self) == type(other) | 132 return type(self) == type(other) and self._target == other._target |
129 and self._target == other._target) | |
130 | 133 |
131 def encode(self): | 134 def encode(self): |
132 return _llentry.pack(0, self._target) | 135 return _llentry.pack(0, self._target) |
133 | 136 |
134 def execute(self, rev, pc, emit): | 137 def execute(self, rev, pc, emit): |
135 return self._target | 138 return self._target |
139 | |
136 | 140 |
137 class _eof(_llinstruction): | 141 class _eof(_llinstruction): |
138 """EOF is expressed as a JGE that always jumps to 0.""" | 142 """EOF is expressed as a JGE that always jumps to 0.""" |
139 | 143 |
140 def __init__(self, op1, op2): | 144 def __init__(self, op1, op2): |
153 return _llentry.pack(0, 0) | 157 return _llentry.pack(0, 0) |
154 | 158 |
155 def execute(self, rev, pc, emit): | 159 def execute(self, rev, pc, emit): |
156 return None | 160 return None |
157 | 161 |
162 | |
158 class _jl(_llinstruction): | 163 class _jl(_llinstruction): |
159 """If the current rev is less than op1, jump to op2.""" | 164 """If the current rev is less than op1, jump to op2.""" |
160 | 165 |
161 def __init__(self, op1, op2): | 166 def __init__(self, op1, op2): |
162 self._cmprev = op1 | 167 self._cmprev = op1 |
164 | 169 |
165 def __str__(self): | 170 def __str__(self): |
166 return r'JL %d %d' % (self._cmprev, self._target) | 171 return r'JL %d %d' % (self._cmprev, self._target) |
167 | 172 |
168 def __eq__(self, other): | 173 def __eq__(self, other): |
169 return (type(self) == type(other) | 174 return ( |
170 and self._cmprev == other._cmprev | 175 type(self) == type(other) |
171 and self._target == other._target) | 176 and self._cmprev == other._cmprev |
177 and self._target == other._target | |
178 ) | |
172 | 179 |
173 def encode(self): | 180 def encode(self): |
174 return _llentry.pack(1 | (self._cmprev << 2), self._target) | 181 return _llentry.pack(1 | (self._cmprev << 2), self._target) |
175 | 182 |
176 def execute(self, rev, pc, emit): | 183 def execute(self, rev, pc, emit): |
177 if rev < self._cmprev: | 184 if rev < self._cmprev: |
178 return self._target | 185 return self._target |
179 return pc + 1 | 186 return pc + 1 |
187 | |
180 | 188 |
181 class _line(_llinstruction): | 189 class _line(_llinstruction): |
182 """Emit a line.""" | 190 """Emit a line.""" |
183 | 191 |
184 def __init__(self, op1, op2): | 192 def __init__(self, op1, op2): |
189 | 197 |
190 def __str__(self): | 198 def __str__(self): |
191 return r'LINE %d %d' % (self._rev, self._origlineno) | 199 return r'LINE %d %d' % (self._rev, self._origlineno) |
192 | 200 |
193 def __eq__(self, other): | 201 def __eq__(self, other): |
194 return (type(self) == type(other) | 202 return ( |
195 and self._rev == other._rev | 203 type(self) == type(other) |
196 and self._origlineno == other._origlineno) | 204 and self._rev == other._rev |
205 and self._origlineno == other._origlineno | |
206 ) | |
197 | 207 |
198 def encode(self): | 208 def encode(self): |
199 return _llentry.pack(2 | (self._rev << 2), self._origlineno) | 209 return _llentry.pack(2 | (self._rev << 2), self._origlineno) |
200 | 210 |
201 def execute(self, rev, pc, emit): | 211 def execute(self, rev, pc, emit): |
202 emit(lineinfo(self._rev, self._origlineno, pc)) | 212 emit(lineinfo(self._rev, self._origlineno, pc)) |
203 return pc + 1 | 213 return pc + 1 |
214 | |
204 | 215 |
205 def _decodeone(data, offset): | 216 def _decodeone(data, offset): |
206 """Decode a single linelog instruction from an offset in a buffer.""" | 217 """Decode a single linelog instruction from an offset in a buffer.""" |
207 try: | 218 try: |
208 op1, op2 = _llentry.unpack_from(data, offset) | 219 op1, op2 = _llentry.unpack_from(data, offset) |
220 return _jl(op1, op2) | 231 return _jl(op1, op2) |
221 elif opcode == 2: | 232 elif opcode == 2: |
222 return _line(op1, op2) | 233 return _line(op1, op2) |
223 raise NotImplementedError('Unimplemented opcode %r' % opcode) | 234 raise NotImplementedError('Unimplemented opcode %r' % opcode) |
224 | 235 |
236 | |
225 class linelog(object): | 237 class linelog(object): |
226 """Efficient cache for per-line history information.""" | 238 """Efficient cache for per-line history information.""" |
227 | 239 |
228 def __init__(self, program=None, maxrev=0): | 240 def __init__(self, program=None, maxrev=0): |
229 if program is None: | 241 if program is None: |
234 self._program = program | 246 self._program = program |
235 self._lastannotate = None | 247 self._lastannotate = None |
236 self._maxrev = maxrev | 248 self._maxrev = maxrev |
237 | 249 |
238 def __eq__(self, other): | 250 def __eq__(self, other): |
239 return (type(self) == type(other) | 251 return ( |
240 and self._program == other._program | 252 type(self) == type(other) |
241 and self._maxrev == other._maxrev) | 253 and self._program == other._program |
254 and self._maxrev == other._maxrev | |
255 ) | |
242 | 256 |
243 def __repr__(self): | 257 def __repr__(self): |
244 return '<linelog at %s: maxrev=%d size=%d>' % ( | 258 return '<linelog at %s: maxrev=%d size=%d>' % ( |
245 hex(id(self)), self._maxrev, len(self._program)) | 259 hex(id(self)), |
260 self._maxrev, | |
261 len(self._program), | |
262 ) | |
246 | 263 |
247 def debugstr(self): | 264 def debugstr(self): |
248 fmt = r'%%%dd %%s' % len(str(len(self._program))) | 265 fmt = r'%%%dd %%s' % len(str(len(self._program))) |
249 return pycompat.sysstr('\n').join( | 266 return pycompat.sysstr('\n').join( |
250 fmt % (idx, i) for idx, i in enumerate(self._program[1:], 1)) | 267 fmt % (idx, i) for idx, i in enumerate(self._program[1:], 1) |
268 ) | |
251 | 269 |
252 @classmethod | 270 @classmethod |
253 def fromdata(cls, buf): | 271 def fromdata(cls, buf): |
254 if len(buf) % _llentry.size != 0: | 272 if len(buf) % _llentry.size != 0: |
255 raise LineLogError( | 273 raise LineLogError( |
256 "invalid linelog buffer size %d (must be a multiple of %d)" % ( | 274 "invalid linelog buffer size %d (must be a multiple of %d)" |
257 len(buf), _llentry.size)) | 275 % (len(buf), _llentry.size) |
276 ) | |
258 expected = len(buf) / _llentry.size | 277 expected = len(buf) / _llentry.size |
259 fakejge = _decodeone(buf, 0) | 278 fakejge = _decodeone(buf, 0) |
260 if isinstance(fakejge, _jump): | 279 if isinstance(fakejge, _jump): |
261 maxrev = 0 | 280 maxrev = 0 |
262 else: | 281 else: |
263 maxrev = fakejge._cmprev | 282 maxrev = fakejge._cmprev |
264 numentries = fakejge._target | 283 numentries = fakejge._target |
265 if expected != numentries: | 284 if expected != numentries: |
266 raise LineLogError("corrupt linelog data: claimed" | 285 raise LineLogError( |
267 " %d entries but given data for %d entries" % ( | 286 "corrupt linelog data: claimed" |
268 expected, numentries)) | 287 " %d entries but given data for %d entries" |
288 % (expected, numentries) | |
289 ) | |
269 instructions = [_eof(0, 0)] | 290 instructions = [_eof(0, 0)] |
270 for offset in pycompat.xrange(1, numentries): | 291 for offset in pycompat.xrange(1, numentries): |
271 instructions.append(_decodeone(buf, offset * _llentry.size)) | 292 instructions.append(_decodeone(buf, offset * _llentry.size)) |
272 return cls(instructions, maxrev=maxrev) | 293 return cls(instructions, maxrev=maxrev) |
273 | 294 |
279 self._program = [] | 300 self._program = [] |
280 self._maxrev = 0 | 301 self._maxrev = 0 |
281 self._lastannotate = None | 302 self._lastannotate = None |
282 | 303 |
283 def replacelines_vec(self, rev, a1, a2, blines): | 304 def replacelines_vec(self, rev, a1, a2, blines): |
284 return self.replacelines(rev, a1, a2, 0, len(blines), | 305 return self.replacelines( |
285 _internal_blines=blines) | 306 rev, a1, a2, 0, len(blines), _internal_blines=blines |
307 ) | |
286 | 308 |
287 def replacelines(self, rev, a1, a2, b1, b2, _internal_blines=None): | 309 def replacelines(self, rev, a1, a2, b1, b2, _internal_blines=None): |
288 """Replace lines [a1, a2) with lines [b1, b2).""" | 310 """Replace lines [a1, a2) with lines [b1, b2).""" |
289 if self._lastannotate: | 311 if self._lastannotate: |
290 # TODO(augie): make replacelines() accept a revision at | 312 # TODO(augie): make replacelines() accept a revision at |
296 else: | 318 else: |
297 ar = self.annotate(rev) | 319 ar = self.annotate(rev) |
298 # ar = self.annotate(self._maxrev) | 320 # ar = self.annotate(self._maxrev) |
299 if a1 > len(ar.lines): | 321 if a1 > len(ar.lines): |
300 raise LineLogError( | 322 raise LineLogError( |
301 '%d contains %d lines, tried to access line %d' % ( | 323 '%d contains %d lines, tried to access line %d' |
302 rev, len(ar.lines), a1)) | 324 % (rev, len(ar.lines), a1) |
325 ) | |
303 elif a1 == len(ar.lines): | 326 elif a1 == len(ar.lines): |
304 # Simulated EOF instruction since we're at EOF, which | 327 # Simulated EOF instruction since we're at EOF, which |
305 # doesn't have a "real" line. | 328 # doesn't have a "real" line. |
306 a1inst = _eof(0, 0) | 329 a1inst = _eof(0, 0) |
307 a1info = lineinfo(0, 0, ar._eof) | 330 a1info = lineinfo(0, 0, ar._eof) |
331 appendinst(_line(newrev, newlinenum)) | 354 appendinst(_line(newrev, newlinenum)) |
332 # delete | 355 # delete |
333 if a1 < a2: | 356 if a1 < a2: |
334 if a2 > len(ar.lines): | 357 if a2 > len(ar.lines): |
335 raise LineLogError( | 358 raise LineLogError( |
336 '%d contains %d lines, tried to access line %d' % ( | 359 '%d contains %d lines, tried to access line %d' |
337 rev, len(ar.lines), a2)) | 360 % (rev, len(ar.lines), a2) |
361 ) | |
338 elif a2 == len(ar.lines): | 362 elif a2 == len(ar.lines): |
339 endaddr = ar._eof | 363 endaddr = ar._eof |
340 else: | 364 else: |
341 endaddr = ar.lines[a2]._offset | 365 endaddr = ar.lines[a2]._offset |
342 if a2 > 0 and rev < self._maxrev: | 366 if a2 > 0 and rev < self._maxrev: |
382 lastpc = pc | 406 lastpc = pc |
383 pc = inst.execute(rev, pc, lines.append) | 407 pc = inst.execute(rev, pc, lines.append) |
384 executed += 1 | 408 executed += 1 |
385 if pc is not None: | 409 if pc is not None: |
386 raise LineLogError( | 410 raise LineLogError( |
387 r'Probably hit an infinite loop in linelog. Program:\n' + | 411 r'Probably hit an infinite loop in linelog. Program:\n' |
388 self.debugstr()) | 412 + self.debugstr() |
413 ) | |
389 ar = annotateresult(rev, lines, lastpc) | 414 ar = annotateresult(rev, lines, lastpc) |
390 self._lastannotate = ar | 415 self._lastannotate = ar |
391 return ar | 416 return ar |
392 | 417 |
393 @property | 418 @property |