15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
from __future__ import absolute_import
19
20
from bisect import bisect
22
from bzrlib.trace import mutter
25
__all__ = ['PatienceSequenceMatcher', 'unified_diff', 'unified_diff_files']
23
from .trace import mutter
28
26
def unique_lcs_py(a, b):
42
40
# set index[line in a] = position of line in a unless
43
41
# a is a duplicate, in which case it's set to None
45
for i in xrange(len(a)):
43
for i, line in enumerate(a):
51
48
# make btoa[i] = position of line i in a, unless
52
49
# that line doesn't occur exactly once in both,
53
50
# in which case it's set to None
80
77
# as an optimization, check if the next line comes right after
81
78
# the previous line, because usually it does
82
79
elif stacks and stacks[k] < apos and (k == len(stacks) - 1 or
80
stacks[k + 1] > apos):
86
83
k = bisect(stacks, apos)
88
backpointers[bpos] = lasts[k-1]
85
backpointers[bpos] = lasts[k - 1]
89
86
if k < len(stacks):
127
124
oldlength = len(answer)
128
125
if alo == ahi or blo == bhi:
132
129
for apos, bpos in unique_lcs_py(a[alo:ahi], b[blo:bhi]):
133
130
# recurse between lines which are unique in each file and match
136
133
# Most of the time, you will have a sequence of similar entries
137
if last_a_pos+1 != apos or last_b_pos+1 != bpos:
138
recurse_matches_py(a, b, last_a_pos+1, last_b_pos+1,
139
apos, bpos, answer, maxrecursion - 1)
134
if last_a_pos + 1 != apos or last_b_pos + 1 != bpos:
136
a, b, last_a_pos + 1, last_b_pos + 1, apos, bpos, answer,
140
138
last_a_pos = apos
141
139
last_b_pos = bpos
142
140
answer.append((apos, bpos))
143
141
if len(answer) > oldlength:
144
142
# find matches between the last match and the end
145
recurse_matches_py(a, b, last_a_pos+1, last_b_pos+1,
143
recurse_matches_py(a, b, last_a_pos + 1, last_b_pos + 1,
146
144
ahi, bhi, answer, maxrecursion - 1)
147
145
elif a[alo] == b[blo]:
148
146
# find matching lines at the very beginning
159
157
while nahi > alo and nbhi > blo and a[nahi - 1] == b[nbhi - 1]:
162
recurse_matches_py(a, b, last_a_pos+1, last_b_pos+1,
160
recurse_matches_py(a, b, last_a_pos + 1, last_b_pos + 1,
163
161
nahi, nbhi, answer, maxrecursion - 1)
164
for i in xrange(ahi - nahi):
162
for i in range(ahi - nahi):
165
163
answer.append((nahi + i, nbhi + i))
244
242
# Matches now has individual line pairs of
245
243
# line A matches line B, at the given offsets
246
244
self.matching_blocks = _collapse_sequences(matches)
247
self.matching_blocks.append( (len(self.a), len(self.b), 0) )
245
self.matching_blocks.append((len(self.a), len(self.b), 0))
248
246
if PatienceSequenceMatcher_py._do_check_consistency:
250
248
_check_consistency(self.matching_blocks)