67
67
Given BASE, OTHER, THIS, tries to produce a combined text
68
68
incorporating the changes from both BASE->OTHER and BASE->THIS.
69
69
All three will typically be sequences of lines."""
70
def __init__(self, base, a, b):
70
def __init__(self, base, a, b, is_cherrypick=False):
71
71
check_text_lines(base)
72
72
check_text_lines(a)
73
73
check_text_lines(b)
77
self.is_cherrypick = is_cherrypick
80
79
def merge_lines(self,
251
241
if len_a or len_b:
252
242
# try to avoid actually slicing the lists
253
equal_a = compare_range(self.a, ia, amatch,
254
self.base, iz, zmatch)
255
equal_b = compare_range(self.b, ib, bmatch,
256
self.base, iz, zmatch)
257
243
same = compare_range(self.a, ia, amatch,
258
244
self.b, ib, bmatch)
261
247
yield 'same', ia, amatch
262
elif equal_a and not equal_b:
263
yield 'b', ib, bmatch
264
elif equal_b and not equal_a:
265
yield 'a', ia, amatch
266
elif not equal_a and not equal_b:
267
yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
269
raise AssertionError("can't handle a=b=base but unmatched")
249
equal_a = compare_range(self.a, ia, amatch,
250
self.base, iz, zmatch)
251
equal_b = compare_range(self.b, ib, bmatch,
252
self.base, iz, zmatch)
253
if equal_a and not equal_b:
254
yield 'b', ib, bmatch
255
elif equal_b and not equal_a:
256
yield 'a', ia, amatch
257
elif not equal_a and not equal_b:
258
if self.is_cherrypick:
259
for node in self._refine_cherrypick_conflict(
260
iz, zmatch, ia, amatch,
264
yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
266
raise AssertionError("can't handle a=b=base but unmatched")
285
def _refine_cherrypick_conflict(self, zstart, zend, astart, aend, bstart, bend):
286
"""When cherrypicking b => a, ignore matches with b and base."""
287
# Do not emit regions which match, only regions which do not match
288
matches = bzrlib.patiencediff.PatienceSequenceMatcher(None,
289
self.base[zstart:zend], self.b[bstart:bend]).get_matching_blocks()
294
for base_idx, b_idx, match_len in matches:
295
conflict_z_len = base_idx - last_base_idx
296
conflict_b_len = b_idx - last_b_idx
297
if conflict_b_len == 0: # There are no lines in b which conflict,
303
zstart + last_base_idx, zstart + base_idx,
304
aend, aend, bstart + last_b_idx, bstart + b_idx)
306
# The first conflict gets the a-range
308
yield ('conflict', zstart + last_base_idx, zstart +
310
astart, aend, bstart + last_b_idx, bstart + b_idx)
311
last_base_idx = base_idx + match_len
312
last_b_idx = b_idx + match_len
313
if last_base_idx != zend - zstart or last_b_idx != bend - bstart:
315
yield ('conflict', zstart + last_base_idx, zstart + base_idx,
316
aend, aend, bstart + last_b_idx, bstart + b_idx)
318
# The first conflict gets the a-range
320
yield ('conflict', zstart + last_base_idx, zstart + base_idx,
321
astart, aend, bstart + last_b_idx, bstart + b_idx)
323
yield ('conflict', zstart, zend, astart, aend, bstart, bend)
290
325
def reprocess_merge_regions(self, merge_regions):
291
326
"""Where there are conflict regions, remove the agreed lines.
318
353
if reg is not None:
323
357
def mismatch_region(next_a, region_ia, next_b, region_ib):
324
358
if next_a < region_ia or next_b < region_ib:
325
359
return 'conflict', None, None, next_a, region_ia, next_b, region_ib
328
361
def find_sync_regions(self):
329
362
"""Return a list of sync regions, where both descendents match the base.