105
108
[b'aaa', b'bbb'])
107
110
self.assertEqual(m3.find_unconflicted(),
110
113
self.assertEqual(list(m3.find_sync_regions()),
116
119
self.assertEqual(list(m3.merge_regions()),
117
[('unchanged', 0, 2)])
120
[('unchanged', 0, 2)])
119
122
self.assertEqual(list(m3.merge_groups()),
120
[('unchanged', [b'aaa', b'bbb'])])
123
[('unchanged', [b'aaa', b'bbb'])])
122
125
def test_front_insert(self):
123
126
m3 = merge3.Merge3([b'zz'],
127
130
# todo: should use a sentinal at end as from get_matching_blocks
128
131
# to match without zz
129
132
self.assertEqual(list(m3.find_sync_regions()),
131
(1, 1, 3, 3, 1, 1),])
134
(1, 1, 3, 3, 1, 1), ])
133
136
self.assertEqual(list(m3.merge_regions()),
135
('unchanged', 0, 1)])
138
('unchanged', 0, 1)])
137
140
self.assertEqual(list(m3.merge_groups()),
138
[('a', [b'aaa', b'bbb']),
139
('unchanged', [b'zz'])])
141
[('a', [b'aaa', b'bbb']),
142
('unchanged', [b'zz'])])
141
144
def test_null_insert(self):
142
145
m3 = merge3.Merge3([],
145
148
# todo: should use a sentinal at end as from get_matching_blocks
146
149
# to match without zz
147
150
self.assertEqual(list(m3.find_sync_regions()),
148
[(0, 0, 2, 2, 0, 0)])
151
[(0, 0, 2, 2, 0, 0)])
150
153
self.assertEqual(list(m3.merge_regions()),
153
156
self.assertEqual(list(m3.merge_lines()),
156
159
def test_no_conflicts(self):
157
160
"""No conflicts because only one side changed"""
160
163
[b'aaa', b'bbb'])
162
165
self.assertEqual(m3.find_unconflicted(),
165
168
self.assertEqual(list(m3.find_sync_regions()),
168
(2, 2, 3, 3, 2, 2),])
171
(2, 2, 3, 3, 2, 2), ])
170
173
self.assertEqual(list(m3.merge_regions()),
171
[('unchanged', 0, 1),
173
('unchanged', 1, 2),])
174
[('unchanged', 0, 1),
176
('unchanged', 1, 2), ])
175
178
def test_append_a(self):
176
179
m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
186
189
[b'aaa\n', b'bbb\n', b'222\n'])
188
191
self.assertEqual(b''.join(m3.merge_lines()),
191
194
def test_append_agreement(self):
192
195
m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
194
197
[b'aaa\n', b'bbb\n', b'222\n'])
196
199
self.assertEqual(b''.join(m3.merge_lines()),
199
202
def test_append_clash(self):
200
203
m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
229
232
end_marker=b'>>')
230
233
self.assertEqual(b''.join(ml), b'aaa\n222\nbbb\n')
233
235
def test_insert_clash(self):
234
236
"""Both try to insert lines in the same place."""
235
237
m3 = merge3.Merge3([b'aaa\n', b'bbb\n'],
237
239
[b'aaa\n', b'222\n', b'bbb\n'])
239
241
self.assertEqual(m3.find_unconflicted(),
242
244
self.assertEqual(list(m3.find_sync_regions()),
245
(2, 2, 3, 3, 3, 3),])
247
(2, 2, 3, 3, 3, 3), ])
247
249
self.assertEqual(list(m3.merge_regions()),
248
[('unchanged', 0, 1),
249
('conflict', 1, 1, 1, 2, 1, 2),
250
('unchanged', 1, 2)])
250
[('unchanged', 0, 1),
251
('conflict', 1, 1, 1, 2, 1, 2),
252
('unchanged', 1, 2)])
252
254
self.assertEqual(list(m3.merge_groups()),
253
[('unchanged', [b'aaa\n']),
254
('conflict', [], [b'111\n'], [b'222\n']),
255
('unchanged', [b'bbb\n']),
255
[('unchanged', [b'aaa\n']),
256
('conflict', [], [b'111\n'], [b'222\n']),
257
('unchanged', [b'bbb\n']),
258
260
ml = m3.merge_lines(name_a=b'a',
277
279
[b'aaa', b'222', b'bbb'])
279
281
self.assertEqual(m3.find_unconflicted(),
282
284
self.assertEqual(list(m3.find_sync_regions()),
285
(3, 3, 3, 3, 3, 3),])
287
(3, 3, 3, 3, 3, 3), ])
287
289
def test_replace_multi(self):
288
290
"""Replacement with regions of different size."""
291
293
[b'aaa', b'222', b'222', b'222', b'222', b'bbb'])
293
295
self.assertEqual(m3.find_unconflicted(),
297
298
self.assertEqual(list(m3.find_sync_regions()),
300
(4, 4, 5, 5, 6, 6),])
301
(4, 4, 5, 5, 6, 6), ])
302
303
def test_merge_poem(self):
303
304
"""Test case from diff3 manual"""
310
311
def test_minimal_conflicts_common(self):
311
312
"""Reprocessing"""
312
313
base_text = (b"a\n" * 20).splitlines(True)
313
this_text = (b"a\n"*10+b"b\n" * 10).splitlines(True)
314
other_text = (b"a\n"*10+b"c\n"+b"b\n" * 8 + b"c\n").splitlines(True)
314
this_text = (b"a\n" * 10 + b"b\n" * 10).splitlines(True)
315
other_text = (b"a\n" * 10 + b"c\n" + b"b\n" *
316
8 + b"c\n").splitlines(True)
315
317
m3 = merge3.Merge3(base_text, other_text, this_text)
316
318
m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True)
317
319
merged_text = b"".join(list(m_lines))
318
320
optimal_text = (b"a\n" * 10 + b"<<<<<<< OTHER\nc\n"
319
+ 8* b"b\n" + b"c\n=======\n"
320
+ 10*b"b\n" + b">>>>>>> THIS\n")
321
+ 8 * b"b\n" + b"c\n=======\n"
322
+ 10 * b"b\n" + b">>>>>>> THIS\n")
321
323
self.assertEqualDiff(optimal_text, merged_text)
323
325
def test_minimal_conflicts_unique(self):
324
326
def add_newline(s):
325
327
"""Add a newline to each entry in the string"""
326
return [(int2byte(x)+b'\n') for x in bytearray(s)]
328
return [(int2byte(x) + b'\n') for x in bytearray(s)]
328
330
base_text = add_newline(b"abcdefghijklm")
329
331
this_text = add_newline(b"abcdefghijklmNOPQRSTUVWXYZ")
332
334
m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True)
333
335
merged_text = b"".join(list(m_lines))
334
336
optimal_text = b''.join(add_newline(b"abcdefghijklm")
335
+ [b"<<<<<<< OTHER\n1\n=======\nN\n>>>>>>> THIS\n"]
336
+ add_newline(b'OPQRSTUVWXY')
337
+ [b"<<<<<<< OTHER\n2\n=======\nZ\n>>>>>>> THIS\n"]
337
+ [b"<<<<<<< OTHER\n1\n=======\nN\n>>>>>>> THIS\n"]
338
+ add_newline(b'OPQRSTUVWXY')
339
+ [b"<<<<<<< OTHER\n2\n=======\nZ\n>>>>>>> THIS\n"]
339
341
self.assertEqualDiff(optimal_text, merged_text)
341
343
def test_minimal_conflicts_nonunique(self):
342
344
def add_newline(s):
343
345
"""Add a newline to each entry in the string"""
344
return [(int2byte(x)+b'\n') for x in bytearray(s)]
346
return [(int2byte(x) + b'\n') for x in bytearray(s)]
346
348
base_text = add_newline(b"abacddefgghij")
347
349
this_text = add_newline(b"abacddefgghijkalmontfprz")
350
352
m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True)
351
353
merged_text = b"".join(list(m_lines))
352
354
optimal_text = b''.join(add_newline(b"abacddefgghijk")
353
+ [b"<<<<<<< OTHER\nn\n=======\na\n>>>>>>> THIS\n"]
354
+ add_newline(b'lmontfpr')
355
+ [b"<<<<<<< OTHER\nd\n=======\nz\n>>>>>>> THIS\n"]
355
+ [b"<<<<<<< OTHER\nn\n=======\na\n>>>>>>> THIS\n"]
356
+ add_newline(b'lmontfpr')
357
+ [b"<<<<<<< OTHER\nd\n=======\nz\n>>>>>>> THIS\n"]
357
359
self.assertEqualDiff(optimal_text, merged_text)
359
361
def test_reprocess_and_base(self):
360
362
"""Reprocessing and showing base breaks correctly"""
361
363
base_text = (b"a\n" * 20).splitlines(True)
362
this_text = (b"a\n"*10+b"b\n" * 10).splitlines(True)
363
other_text = (b"a\n"*10+b"c\n"+b"b\n" * 8 + b"c\n").splitlines(True)
364
this_text = (b"a\n" * 10 + b"b\n" * 10).splitlines(True)
365
other_text = (b"a\n" * 10 + b"c\n" + b"b\n" *
366
8 + b"c\n").splitlines(True)
364
367
m3 = merge3.Merge3(base_text, other_text, this_text)
365
368
m_lines = m3.merge_lines(b'OTHER', b'THIS', reprocess=True,
366
369
base_marker=b'|||||||')
378
381
this_text.splitlines(True))
379
382
m_lines = m3.merge_lines(b'OTHER', b'THIS')
380
383
self.assertEqual(b'<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
381
b'>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
384
b'>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
383
386
def test_mac_text(self):
384
387
base_text = b'a\r'
389
392
this_text.splitlines(True))
390
393
m_lines = m3.merge_lines(b'OTHER', b'THIS')
391
394
self.assertEqual(b'<<<<<<< OTHER\rc\r=======\rb\r'
392
b'>>>>>>> THIS\r'.splitlines(True), list(m_lines))
395
b'>>>>>>> THIS\r'.splitlines(True), list(m_lines))
394
397
def test_merge3_cherrypick(self):
395
398
base_text = b"a\nb\n"