annotate mercurial/linelog.py @ 42522:d29db0a0c4eb

update: fix spurious unclean status bug shown by previous commit The crux of the problem is: - the dirstate is corrupted (the sizes/dates are assigned to the wrong files) - because when worker.worker is used with a return value (batchget in merge.py here), the return value when worker.worker effectively parallelizes is permuted - this is because worker.worker's partition of input and combination of output values are not inverses of one another: it split [1,2,3,4,5,6] into [[1,3,5],[2,4,6]], but combines that into [1,3,5,2,4,6]. Given that worker.worker doesn't call its function argument on contiguous chunks on the input arguments, sticking with lists means we'd need to know the relation between the inputs of worker.worker function argument (for instance, requiring that every input element is mapped to exactly one output element). It seems better to instead switch return values to dicts, which can combined reliably with a straighforward restriction. Differential Revision: https://phab.mercurial-scm.org/D6581
author Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
date Thu, 27 Jun 2019 11:39:35 +0200
parents ee97f7a677f3
children 2372284d9457
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
1 # linelog - efficient cache for annotate data
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
2 #
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
3 # Copyright 2018 Google LLC.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
4 #
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
7 """linelog is an efficient cache for annotate data inspired by SCCS Weaves.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
8
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
9 SCCS Weaves are an implementation of
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
10 https://en.wikipedia.org/wiki/Interleaved_deltas. See
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
11 mercurial/help/internals/linelog.txt for an exploration of SCCS weaves
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
12 and how linelog works in detail.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
13
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
14 Here's a hacker's summary: a linelog is a program which is executed in
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
15 the context of a revision. Executing the program emits information
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
16 about lines, including the revision that introduced them and the line
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
17 number in the file at the introducing revision. When an insertion or
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
18 deletion is performed on the file, a jump instruction is used to patch
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
19 in a new body of annotate information.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
20 """
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
21 from __future__ import absolute_import, print_function
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
22
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
23 import abc
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
24 import struct
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
25
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
26 from .thirdparty import (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
27 attr,
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
28 )
38796
f956dc7217fc linelog: fix import statements to pass the import checker on py3
Augie Fackler <augie@google.com>
parents: 38795
diff changeset
29 from . import (
f956dc7217fc linelog: fix import statements to pass the import checker on py3
Augie Fackler <augie@google.com>
parents: 38795
diff changeset
30 pycompat,
f956dc7217fc linelog: fix import statements to pass the import checker on py3
Augie Fackler <augie@google.com>
parents: 38795
diff changeset
31 )
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
32
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
33 _llentry = struct.Struct('>II')
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
34
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
35 class LineLogError(Exception):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
36 """Error raised when something bad happens internally in linelog."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
37
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
38 @attr.s
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
39 class lineinfo(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
40 # Introducing revision of this line.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
41 rev = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
42 # Line number for this line in its introducing revision.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
43 linenum = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
44 # Private. Offset in the linelog program of this line. Used internally.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
45 _offset = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
46
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
47 @attr.s
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
48 class annotateresult(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
49 rev = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
50 lines = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
51 _eof = attr.ib()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
52
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
53 def __iter__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
54 return iter(self.lines)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
55
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
56 class _llinstruction(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
57
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
58 __metaclass__ = abc.ABCMeta
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
59
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
60 @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
61 def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
62 pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
63
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
64 @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
65 def __str__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
66 pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
67
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
68 def __repr__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
69 return str(self)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
70
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
71 @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
72 def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
73 pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
74
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
75 @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
76 def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
77 """Encode this instruction to the binary linelog format."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
78
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
79 @abc.abstractmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
80 def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
81 """Execute this instruction.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
82
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
83 Args:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
84 rev: The revision we're annotating.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
85 pc: The current offset in the linelog program.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
86 emit: A function that accepts a single lineinfo object.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
87
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
88 Returns:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
89 The new value of pc. Returns None if exeuction should stop
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
90 (that is, we've found the end of the file.)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
91 """
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
92
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
93 class _jge(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
94 """If the current rev is greater than or equal to op1, jump to op2."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
95
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
96 def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
97 self._cmprev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
98 self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
99
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
100 def __str__(self):
38809
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
101 return r'JGE %d %d' % (self._cmprev, self._target)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
102
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
103 def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
104 return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
105 and self._cmprev == other._cmprev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
106 and self._target == other._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
107
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
108 def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
109 return _llentry.pack(self._cmprev << 2, self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
110
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
111 def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
112 if rev >= self._cmprev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
113 return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
114 return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
115
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
116 class _jump(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
117 """Unconditional jumps are expressed as a JGE with op1 set to 0."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
118
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
119 def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
120 if op1 != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
121 raise LineLogError("malformed JUMP, op1 must be 0, got %d" % op1)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
122 self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
123
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
124 def __str__(self):
38809
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
125 return r'JUMP %d' % (self._target)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
126
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
127 def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
128 return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
129 and self._target == other._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
130
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
131 def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
132 return _llentry.pack(0, self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
133
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
134 def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
135 return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
136
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
137 class _eof(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
138 """EOF is expressed as a JGE that always jumps to 0."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
139
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
140 def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
141 if op1 != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
142 raise LineLogError("malformed EOF, op1 must be 0, got %d" % op1)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
143 if op2 != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
144 raise LineLogError("malformed EOF, op2 must be 0, got %d" % op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
145
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
146 def __str__(self):
38809
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
147 return r'EOF'
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
148
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
149 def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
150 return type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
151
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
152 def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
153 return _llentry.pack(0, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
154
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
155 def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
156 return None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
157
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
158 class _jl(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
159 """If the current rev is less than op1, jump to op2."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
160
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
161 def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
162 self._cmprev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
163 self._target = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
164
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
165 def __str__(self):
38809
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
166 return r'JL %d %d' % (self._cmprev, self._target)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
167
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
168 def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
169 return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
170 and self._cmprev == other._cmprev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
171 and self._target == other._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
172
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
173 def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
174 return _llentry.pack(1 | (self._cmprev << 2), self._target)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
175
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
176 def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
177 if rev < self._cmprev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
178 return self._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
179 return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
180
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
181 class _line(_llinstruction):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
182 """Emit a line."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
183
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
184 def __init__(self, op1, op2):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
185 # This line was introduced by this revision number.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
186 self._rev = op1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
187 # This line had the specified line number in the introducing revision.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
188 self._origlineno = op2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
189
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
190 def __str__(self):
38809
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
191 return r'LINE %d %d' % (self._rev, self._origlineno)
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
192
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
193 def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
194 return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
195 and self._rev == other._rev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
196 and self._origlineno == other._origlineno)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
197
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
198 def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
199 return _llentry.pack(2 | (self._rev << 2), self._origlineno)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
200
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
201 def execute(self, rev, pc, emit):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
202 emit(lineinfo(self._rev, self._origlineno, pc))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
203 return pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
204
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
205 def _decodeone(data, offset):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
206 """Decode a single linelog instruction from an offset in a buffer."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
207 try:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
208 op1, op2 = _llentry.unpack_from(data, offset)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
209 except struct.error as e:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
210 raise LineLogError('reading an instruction failed: %r' % e)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
211 opcode = op1 & 0b11
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
212 op1 = op1 >> 2
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
213 if opcode == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
214 if op1 == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
215 if op2 == 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
216 return _eof(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
217 return _jump(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
218 return _jge(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
219 elif opcode == 1:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
220 return _jl(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
221 elif opcode == 2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
222 return _line(op1, op2)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
223 raise NotImplementedError('Unimplemented opcode %r' % opcode)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
224
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
225 class linelog(object):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
226 """Efficient cache for per-line history information."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
227
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
228 def __init__(self, program=None, maxrev=0):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
229 if program is None:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
230 # We pad the program with an extra leading EOF so that our
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
231 # offsets will match the C code exactly. This means we can
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
232 # interoperate with the C code.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
233 program = [_eof(0, 0), _eof(0, 0)]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
234 self._program = program
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
235 self._lastannotate = None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
236 self._maxrev = maxrev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
237
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
238 def __eq__(self, other):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
239 return (type(self) == type(other)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
240 and self._program == other._program
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
241 and self._maxrev == other._maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
242
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
243 def __repr__(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
244 return '<linelog at %s: maxrev=%d size=%d>' % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
245 hex(id(self)), self._maxrev, len(self._program))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
246
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
247 def debugstr(self):
38809
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
248 fmt = r'%%%dd %%s' % len(str(len(self._program)))
57af5ee15b35 linelog: port to Python 3
Augie Fackler <augie@google.com>
parents: 38796
diff changeset
249 return pycompat.sysstr('\n').join(
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
250 fmt % (idx, i) for idx, i in enumerate(self._program[1:], 1))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
251
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
252 @classmethod
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
253 def fromdata(cls, buf):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
254 if len(buf) % _llentry.size != 0:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
255 raise LineLogError(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
256 "invalid linelog buffer size %d (must be a multiple of %d)" % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
257 len(buf), _llentry.size))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
258 expected = len(buf) / _llentry.size
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
259 fakejge = _decodeone(buf, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
260 if isinstance(fakejge, _jump):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
261 maxrev = 0
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
262 else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
263 maxrev = fakejge._cmprev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
264 numentries = fakejge._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
265 if expected != numentries:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
266 raise LineLogError("corrupt linelog data: claimed"
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
267 " %d entries but given data for %d entries" % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
268 expected, numentries))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
269 instructions = [_eof(0, 0)]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
270 for offset in pycompat.xrange(1, numentries):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
271 instructions.append(_decodeone(buf, offset * _llentry.size))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
272 return cls(instructions, maxrev=maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
273
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
274 def encode(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
275 hdr = _jge(self._maxrev, len(self._program)).encode()
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
276 return hdr + ''.join(i.encode() for i in self._program[1:])
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
277
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
278 def clear(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
279 self._program = []
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
280 self._maxrev = 0
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
281 self._lastannotate = None
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
282
38924
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
283 def replacelines_vec(self, rev, a1, a2, blines):
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
284 return self.replacelines(rev, a1, a2, 0, len(blines),
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
285 _internal_blines=blines)
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
286
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
287 def replacelines(self, rev, a1, a2, b1, b2, _internal_blines=None):
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
288 """Replace lines [a1, a2) with lines [b1, b2)."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
289 if self._lastannotate:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
290 # TODO(augie): make replacelines() accept a revision at
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
291 # which we're editing as well as a revision to mark
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
292 # responsible for the edits. In hg-experimental it's
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
293 # stateful like this, so we're doing the same thing to
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
294 # retain compatibility with absorb until that's imported.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
295 ar = self._lastannotate
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
296 else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
297 ar = self.annotate(rev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
298 # ar = self.annotate(self._maxrev)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
299 if a1 > len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
300 raise LineLogError(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
301 '%d contains %d lines, tried to access line %d' % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
302 rev, len(ar.lines), a1))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
303 elif a1 == len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
304 # Simulated EOF instruction since we're at EOF, which
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
305 # doesn't have a "real" line.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
306 a1inst = _eof(0, 0)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
307 a1info = lineinfo(0, 0, ar._eof)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
308 else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
309 a1info = ar.lines[a1]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
310 a1inst = self._program[a1info._offset]
38970
32b1967b8734 linelog: extract `len(self._program)` to a local function
Jun Wu <quark@fb.com>
parents: 38962
diff changeset
311 programlen = self._program.__len__
32b1967b8734 linelog: extract `len(self._program)` to a local function
Jun Wu <quark@fb.com>
parents: 38962
diff changeset
312 oldproglen = programlen()
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
313 appendinst = self._program.append
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
314
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
315 # insert
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
316 blineinfos = []
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
317 bappend = blineinfos.append
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
318 if b1 < b2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
319 # Determine the jump target for the JGE at the start of
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
320 # the new block.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
321 tgt = oldproglen + (b2 - b1 + 1)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
322 # Jump to skip the insert if we're at an older revision.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
323 appendinst(_jl(rev, tgt))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
324 for linenum in pycompat.xrange(b1, b2):
38924
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
325 if _internal_blines is None:
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
326 bappend(lineinfo(rev, linenum, programlen()))
38924
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
327 appendinst(_line(rev, linenum))
6fed8b323651 linelog: add replacelines_vec for fastannotate
Augie Fackler <augie@google.com>
parents: 38809
diff changeset
328 else:
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
329 newrev, newlinenum = _internal_blines[linenum]
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
330 bappend(lineinfo(newrev, newlinenum, programlen()))
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
331 appendinst(_line(newrev, newlinenum))
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
332 # delete
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
333 if a1 < a2:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
334 if a2 > len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
335 raise LineLogError(
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
336 '%d contains %d lines, tried to access line %d' % (
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
337 rev, len(ar.lines), a2))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
338 elif a2 == len(ar.lines):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
339 endaddr = ar._eof
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
340 else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
341 endaddr = ar.lines[a2]._offset
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
342 if a2 > 0 and rev < self._maxrev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
343 # If we're here, we're deleting a chunk of an old
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
344 # commit, so we need to be careful and not touch
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
345 # invisible lines between a2-1 and a2 (IOW, lines that
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
346 # are added later).
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
347 endaddr = ar.lines[a2 - 1]._offset + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
348 appendinst(_jge(rev, endaddr))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
349 # copy instruction from a1
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
350 a1instpc = programlen()
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
351 appendinst(a1inst)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
352 # if a1inst isn't a jump or EOF, then we need to add an unconditional
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
353 # jump back into the program here.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
354 if not isinstance(a1inst, (_jump, _eof)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
355 appendinst(_jump(0, a1info._offset + 1))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
356 # Patch instruction at a1, which makes our patch live.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
357 self._program[a1info._offset] = _jump(0, oldproglen)
38971
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
358
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
359 # Update self._lastannotate in place. This serves as a cache to avoid
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
360 # expensive "self.annotate" in this function, when "replacelines" is
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
361 # used continuously.
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
362 if len(self._lastannotate.lines) > a1:
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
363 self._lastannotate.lines[a1]._offset = a1instpc
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
364 else:
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
365 assert isinstance(a1inst, _eof)
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
366 self._lastannotate._eof = a1instpc
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
367 self._lastannotate.lines[a1:a2] = blineinfos
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
368 self._lastannotate.rev = max(self._lastannotate.rev, rev)
ee97f7a677f3 linelog: optimize replacelines
Jun Wu <quark@fb.com>
parents: 38970
diff changeset
369
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
370 if rev > self._maxrev:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
371 self._maxrev = rev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
372
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
373 def annotate(self, rev):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
374 pc = 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
375 lines = []
38935
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
376 executed = 0
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
377 # Sanity check: if instructions executed exceeds len(program), we
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
378 # hit an infinite loop in the linelog program somehow and we
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
379 # should stop.
38935
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
380 while pc is not None and executed < len(self._program):
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
381 inst = self._program[pc]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
382 lastpc = pc
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
383 pc = inst.execute(rev, pc, lines.append)
38935
27a54096c92e linelog: fix infinite loop vulnerability
Jun Wu <quark@fb.com>
parents: 38924
diff changeset
384 executed += 1
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
385 if pc is not None:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
386 raise LineLogError(
38962
70a19e804deb linelog: fix bytes/str issue in exception raise on Python 3
Augie Fackler <augie@google.com>
parents: 38935
diff changeset
387 r'Probably hit an infinite loop in linelog. Program:\n' +
38795
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
388 self.debugstr())
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
389 ar = annotateresult(rev, lines, lastpc)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
390 self._lastannotate = ar
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
391 return ar
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
392
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
393 @property
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
394 def maxrev(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
395 return self._maxrev
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
396
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
397 # Stateful methods which depend on the value of the last
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
398 # annotation run. This API is for compatiblity with the original
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
399 # linelog, and we should probably consider refactoring it.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
400 @property
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
401 def annotateresult(self):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
402 """Return the last annotation result. C linelog code exposed this."""
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
403 return [(l.rev, l.linenum) for l in self._lastannotate.lines]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
404
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
405 def getoffset(self, line):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
406 return self._lastannotate.lines[line]._offset
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
407
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
408 def getalllines(self, start=0, end=0):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
409 """Get all lines that ever occurred in [start, end).
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
410
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
411 Passing start == end == 0 means "all lines ever".
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
412
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
413 This works in terms of *internal* program offsets, not line numbers.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
414 """
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
415 pc = start or 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
416 lines = []
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
417 # only take as many steps as there are instructions in the
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
418 # program - if we don't find an EOF or our stop-line before
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
419 # then, something is badly broken.
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
420 for step in pycompat.xrange(len(self._program)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
421 inst = self._program[pc]
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
422 nextpc = pc + 1
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
423 if isinstance(inst, _jump):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
424 nextpc = inst._target
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
425 elif isinstance(inst, _eof):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
426 return lines
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
427 elif isinstance(inst, (_jl, _jge)):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
428 pass
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
429 elif isinstance(inst, _line):
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
430 lines.append((inst._rev, inst._origlineno))
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
431 else:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
432 raise LineLogError("Illegal instruction %r" % inst)
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
433 if nextpc == end:
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
434 return lines
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
435 pc = nextpc
422d661056be linelog: add a Python implementation of the linelog datastructure
Augie Fackler <augie@google.com>
parents:
diff changeset
436 raise LineLogError("Failed to perform getalllines")