215
215
tree_z.commit('removed b')
216
216
merge_inner(tree_z.branch, tree_a, base_tree, this_tree=tree_z)
217
217
self.assertEqual([
218
conflicts.MissingParent('Created directory', 'b', 'b-id'),
219
conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
218
conflicts.MissingParent('Created directory', 'b', b'b-id'),
219
conflicts.UnversionedParent('Versioned directory', 'b', b'b-id')],
220
220
tree_z.conflicts())
221
221
merge_inner(tree_a.branch, tree_z.basis_tree(), base_tree,
222
222
this_tree=tree_a)
223
223
self.assertEqual([
224
conflicts.DeletingParent('Not deleting', 'b', 'b-id'),
225
conflicts.UnversionedParent('Versioned directory', 'b', 'b-id')],
224
conflicts.DeletingParent('Not deleting', 'b', b'b-id'),
225
conflicts.UnversionedParent('Versioned directory', 'b', b'b-id')],
226
226
tree_a.conflicts())
228
228
def test_nested_merge(self):
458
458
def test_make_preview_transform(self):
459
459
this_tree = self.make_branch_and_tree('this')
460
self.build_tree_contents([('this/file', '1\n')])
461
this_tree.add('file', 'file-id')
462
this_tree.commit('rev1', rev_id='rev1')
460
self.build_tree_contents([('this/file', b'1\n')])
461
this_tree.add('file', b'file-id')
462
this_tree.commit('rev1', rev_id=b'rev1')
463
463
other_tree = this_tree.controldir.sprout('other').open_workingtree()
464
self.build_tree_contents([('this/file', '1\n2a\n')])
465
this_tree.commit('rev2', rev_id='rev2a')
466
self.build_tree_contents([('other/file', '2b\n1\n')])
467
other_tree.commit('rev2', rev_id='rev2b')
464
self.build_tree_contents([('this/file', b'1\n2a\n')])
465
this_tree.commit('rev2', rev_id=b'rev2a')
466
self.build_tree_contents([('other/file', b'2b\n1\n')])
467
other_tree.commit('rev2', rev_id=b'rev2b')
468
468
this_tree.lock_write()
469
469
self.addCleanup(this_tree.unlock)
470
470
merger = _mod_merge.Merger.from_revision_ids(
471
this_tree, 'rev2b', other_branch=other_tree.branch)
471
this_tree, b'rev2b', other_branch=other_tree.branch)
472
472
merger.merge_type = _mod_merge.Merge3Merger
473
473
tree_merger = merger.make_merger()
474
474
tt = tree_merger.make_preview_transform()
488
488
def test_do_merge(self):
489
489
this_tree = self.make_branch_and_tree('this')
490
self.build_tree_contents([('this/file', '1\n')])
491
this_tree.add('file', 'file-id')
492
this_tree.commit('rev1', rev_id='rev1')
490
self.build_tree_contents([('this/file', b'1\n')])
491
this_tree.add('file', b'file-id')
492
this_tree.commit('rev1', rev_id=b'rev1')
493
493
other_tree = this_tree.controldir.sprout('other').open_workingtree()
494
self.build_tree_contents([('this/file', '1\n2a\n')])
495
this_tree.commit('rev2', rev_id='rev2a')
496
self.build_tree_contents([('other/file', '2b\n1\n')])
497
other_tree.commit('rev2', rev_id='rev2b')
494
self.build_tree_contents([('this/file', b'1\n2a\n')])
495
this_tree.commit('rev2', rev_id=b'rev2a')
496
self.build_tree_contents([('other/file', b'2b\n1\n')])
497
other_tree.commit('rev2', rev_id=b'rev2b')
498
498
this_tree.lock_write()
499
499
self.addCleanup(this_tree.unlock)
500
500
merger = _mod_merge.Merger.from_revision_ids(
501
this_tree, 'rev2b', other_branch=other_tree.branch)
501
this_tree, b'rev2b', other_branch=other_tree.branch)
502
502
merger.merge_type = _mod_merge.Merge3Merger
503
503
tree_merger = merger.make_merger()
504
504
tt = tree_merger.do_merge()
2293
2293
# Have to use a real WT, because BranchBuilder doesn't support exec bit
2294
2294
wt = self.get_wt_from_builder(builder)
2295
2295
os.symlink('bar', 'path/foo')
2296
wt.add(['foo'], ['foo-id'])
2296
wt.add(['foo'], [b'foo-id'])
2297
2297
self.assertEqual('bar', wt.get_symlink_target('foo'))
2298
wt.commit('add symlink', rev_id='F-id')
2298
wt.commit('add symlink', rev_id=b'F-id')
2299
2299
# Reset to D, so that we can merge F
2300
wt.set_parent_ids(['D-id'])
2301
wt.branch.set_last_revision_info(3, 'D-id')
2300
wt.set_parent_ids([b'D-id'])
2301
wt.branch.set_last_revision_info(3, b'D-id')
2303
2303
self.assertIs(None, wt.path2id('foo'))
2304
conflicts = wt.merge_from_branch(wt.branch, to_revision='F-id')
2304
conflicts = wt.merge_from_branch(wt.branch, to_revision=b'F-id')
2305
2305
self.assertEqual(0, conflicts)
2306
self.assertEqual('foo-id', wt.path2id('foo'))
2306
self.assertEqual(b'foo-id', wt.path2id('foo'))
2307
2307
self.assertEqual('bar', wt.get_symlink_target('foo'))
2309
2309
def test_both_sides_revert(self):
2361
2361
wt.lock_write()
2362
2362
self.addCleanup(wt.unlock)
2363
2363
os.symlink('bar', 'path/foo')
2364
wt.add(['foo'], ['foo-id'])
2365
wt.commit('add symlink', rev_id='A-id')
2364
wt.add(['foo'], [b'foo-id'])
2365
wt.commit('add symlink', rev_id=b'A-id')
2366
2366
os.remove('path/foo')
2367
2367
os.symlink('baz', 'path/foo')
2368
wt.commit('foo => baz', rev_id='B-id')
2369
wt.set_last_revision('A-id')
2368
wt.commit('foo => baz', rev_id=b'B-id')
2369
wt.set_last_revision(b'A-id')
2370
2370
wt.branch.set_last_revision_info(1, 'A-id')
2372
wt.commit('C', rev_id='C-id')
2373
wt.merge_from_branch(wt.branch, 'B-id')
2372
wt.commit('C', rev_id=b'C-id')
2373
wt.merge_from_branch(wt.branch, b'B-id')
2374
2374
self.assertEqual('baz', wt.get_symlink_target('foo'))
2375
wt.commit('E merges C & B', rev_id='E-id')
2375
wt.commit('E merges C & B', rev_id=b'E-id')
2376
2376
os.remove('path/foo')
2377
2377
os.symlink('bing', 'path/foo')
2378
wt.commit('F foo => bing', rev_id='F-id')
2378
wt.commit('F foo => bing', rev_id=b'F-id')
2379
2379
wt.set_last_revision('B-id')
2380
wt.branch.set_last_revision_info(2, 'B-id')
2380
wt.branch.set_last_revision_info(2, b'B-id')
2382
wt.merge_from_branch(wt.branch, 'C-id')
2383
wt.commit('D merges B & C', rev_id='D-id')
2384
conflicts = wt.merge_from_branch(wt.branch, to_revision='F-id')
2382
wt.merge_from_branch(wt.branch, b'C-id')
2383
wt.commit('D merges B & C', rev_id=b'D-id')
2384
conflicts = wt.merge_from_branch(wt.branch, to_revision=b'F-id')
2385
2385
self.assertEqual(0, conflicts)
2386
2386
self.assertEqual('bing', wt.get_symlink_target('foo'))
2404
2404
wt.lock_write()
2405
2405
self.addCleanup(wt.unlock)
2406
2406
os.symlink('bar', 'path/foo')
2407
wt.add(['foo'], ['foo-id'])
2408
wt.commit('A add symlink', rev_id='A-id')
2407
wt.add(['foo'], [b'foo-id'])
2408
wt.commit('A add symlink', rev_id=b'A-id')
2409
2409
wt.rename_one('foo', 'barry')
2410
wt.commit('B foo => barry', rev_id='B-id')
2410
wt.commit('B foo => barry', rev_id=b'B-id')
2411
2411
wt.set_last_revision('A-id')
2412
wt.branch.set_last_revision_info(1, 'A-id')
2412
wt.branch.set_last_revision_info(1, b'A-id')
2414
wt.commit('C', rev_id='C-id')
2415
wt.merge_from_branch(wt.branch, 'B-id')
2416
self.assertEqual('barry', wt.id2path('foo-id'))
2414
wt.commit('C', rev_id=b'C-id')
2415
wt.merge_from_branch(wt.branch, b'B-id')
2416
self.assertEqual('barry', wt.id2path(b'foo-id'))
2417
2417
self.assertEqual('bar', wt.get_symlink_target('barry'))
2418
wt.commit('E merges C & B', rev_id='E-id')
2418
wt.commit('E merges C & B', rev_id=b'E-id')
2419
2419
wt.rename_one('barry', 'blah')
2420
wt.commit('F barry => blah', rev_id='F-id')
2421
wt.set_last_revision('B-id')
2422
wt.branch.set_last_revision_info(2, 'B-id')
2420
wt.commit('F barry => blah', rev_id=b'F-id')
2421
wt.set_last_revision(b'B-id')
2422
wt.branch.set_last_revision_info(2, b'B-id')
2424
wt.merge_from_branch(wt.branch, 'C-id')
2425
wt.commit('D merges B & C', rev_id='D-id')
2426
self.assertEqual('barry', wt.id2path('foo-id'))
2424
wt.merge_from_branch(wt.branch, b'C-id')
2425
wt.commit('D merges B & C', rev_id=b'D-id')
2426
self.assertEqual('barry', wt.id2path(b'foo-id'))
2427
2427
# Check the output of the Merger object directly
2428
merger = _mod_merge.Merger.from_revision_ids(wt, 'F-id')
2428
merger = _mod_merge.Merger.from_revision_ids(wt, b'F-id')
2429
2429
merger.merge_type = _mod_merge.Merge3Merger
2430
2430
merge_obj = merger.make_merger()
2431
2431
root_id = wt.path2id('')
2432
2432
entries = list(merge_obj._entries_lca())
2433
2433
# No content change, just a path change
2434
self.assertEqual([('foo-id', False,
2434
self.assertEqual([(b'foo-id', False,
2435
2435
((root_id, [root_id, root_id]), root_id, root_id),
2436
2436
((u'foo', [u'barry', u'foo']), u'blah', u'barry'),
2437
2437
((False, [False, False]), False, False)),
2439
conflicts = wt.merge_from_branch(wt.branch, to_revision='F-id')
2439
conflicts = wt.merge_from_branch(wt.branch, to_revision=b'F-id')
2440
2440
self.assertEqual(0, conflicts)
2441
self.assertEqual('blah', wt.id2path('foo-id'))
2441
self.assertEqual('blah', wt.id2path(b'foo-id'))
2443
2443
def test_symlink_no_content_change(self):
2444
2444
self.requireFeature(features.SymlinkFeature)
2458
2458
wt.lock_write()
2459
2459
self.addCleanup(wt.unlock)
2460
2460
os.symlink('bar', 'path/foo')
2461
wt.add(['foo'], ['foo-id'])
2462
wt.commit('add symlink', rev_id='A-id')
2461
wt.add(['foo'], [b'foo-id'])
2462
wt.commit('add symlink', rev_id=b'A-id')
2463
2463
os.remove('path/foo')
2464
2464
os.symlink('baz', 'path/foo')
2465
wt.commit('foo => baz', rev_id='B-id')
2466
wt.set_last_revision('A-id')
2467
wt.branch.set_last_revision_info(1, 'A-id')
2465
wt.commit('foo => baz', rev_id=b'B-id')
2466
wt.set_last_revision(b'A-id')
2467
wt.branch.set_last_revision_info(1, b'A-id')
2469
wt.commit('C', rev_id='C-id')
2470
wt.merge_from_branch(wt.branch, 'B-id')
2469
wt.commit('C', rev_id=b'C-id')
2470
wt.merge_from_branch(wt.branch, b'B-id')
2471
2471
self.assertEqual('baz', wt.get_symlink_target('foo'))
2472
wt.commit('E merges C & B', rev_id='E-id')
2473
wt.set_last_revision('B-id')
2474
wt.branch.set_last_revision_info(2, 'B-id')
2472
wt.commit('E merges C & B', rev_id=b'E-id')
2473
wt.set_last_revision(b'B-id')
2474
wt.branch.set_last_revision_info(2, b'B-id')
2476
wt.merge_from_branch(wt.branch, 'C-id')
2477
wt.commit('D merges B & C', rev_id='D-id')
2476
wt.merge_from_branch(wt.branch, b'C-id')
2477
wt.commit('D merges B & C', rev_id=b'D-id')
2478
2478
os.remove('path/foo')
2479
2479
os.symlink('bing', 'path/foo')
2480
wt.commit('F foo => bing', rev_id='F-id')
2480
wt.commit('F foo => bing', rev_id=b'F-id')
2482
2482
# Check the output of the Merger object directly
2483
merger = _mod_merge.Merger.from_revision_ids(wt, 'E-id')
2483
merger = _mod_merge.Merger.from_revision_ids(wt, b'E-id')
2484
2484
merger.merge_type = _mod_merge.Merge3Merger
2485
2485
merge_obj = merger.make_merger()
2486
2486
# Nothing interesting happened in OTHER relative to BASE
2487
2487
self.assertEqual([], list(merge_obj._entries_lca()))
2488
2488
# Now do a real merge, just to test the rest of the stack
2489
conflicts = wt.merge_from_branch(wt.branch, to_revision='E-id')
2489
conflicts = wt.merge_from_branch(wt.branch, to_revision=b'E-id')
2490
2490
self.assertEqual(0, conflicts)
2491
2491
self.assertEqual('bing', wt.get_symlink_target('foo'))
2505
2505
wt = self.make_branch_and_tree('path')
2506
2506
wt.lock_write()
2507
2507
self.addCleanup(wt.unlock)
2508
wt.commit('base', rev_id='A-id')
2508
wt.commit('base', rev_id=b'A-id')
2509
2509
os.symlink('bar', 'path/foo')
2510
wt.add(['foo'], ['foo-id'])
2511
wt.commit('add symlink foo => bar', rev_id='B-id')
2512
wt.set_last_revision('A-id')
2513
wt.branch.set_last_revision_info(1, 'A-id')
2510
wt.add(['foo'], [b'foo-id'])
2511
wt.commit('add symlink foo => bar', rev_id=b'B-id')
2512
wt.set_last_revision(b'A-id')
2513
wt.branch.set_last_revision_info(1, b'A-id')
2515
wt.commit('C', rev_id='C-id')
2516
wt.merge_from_branch(wt.branch, 'B-id')
2515
wt.commit('C', rev_id=b'C-id')
2516
wt.merge_from_branch(wt.branch, b'B-id')
2517
2517
self.assertEqual('bar', wt.get_symlink_target('foo'))
2518
2518
os.remove('path/foo')
2519
2519
# We have to change the link in E, or it won't try to do a comparison
2520
2520
os.symlink('bing', 'path/foo')
2521
wt.commit('E merges C & B, overrides to bing', rev_id='E-id')
2521
wt.commit('E merges C & B, overrides to bing', rev_id=b'E-id')
2522
2522
wt.set_last_revision('B-id')
2523
wt.branch.set_last_revision_info(2, 'B-id')
2523
wt.branch.set_last_revision_info(2, b'B-id')
2525
wt.merge_from_branch(wt.branch, 'C-id')
2525
wt.merge_from_branch(wt.branch, b'C-id')
2526
2526
os.remove('path/foo')
2527
self.build_tree_contents([('path/foo', 'file content\n')])
2527
self.build_tree_contents([('path/foo', b'file content\n')])
2528
2528
# XXX: workaround, WT doesn't detect kind changes unless you do
2529
2529
# iter_changes()
2530
2530
list(wt.iter_changes(wt.basis_tree()))
2531
wt.commit('D merges B & C, makes it a file', rev_id='D-id')
2531
wt.commit('D merges B & C, makes it a file', rev_id=b'D-id')
2533
merger = _mod_merge.Merger.from_revision_ids(wt, 'E-id')
2533
merger = _mod_merge.Merger.from_revision_ids(wt, b'E-id')
2534
2534
merger.merge_type = _mod_merge.Merge3Merger
2535
2535
merge_obj = merger.make_merger()
2536
2536
entries = list(merge_obj._entries_lca())
2537
2537
root_id = wt.path2id('')
2538
self.assertEqual([('foo-id', True,
2538
self.assertEqual([(b'foo-id', True,
2539
2539
((None, [root_id, None]), root_id, root_id),
2540
2540
((None, [u'foo', None]), u'foo', u'foo'),
2541
2541
((None, [False, None]), False, False)),
2560
2560
wt.lock_write()
2561
2561
self.addCleanup(wt.unlock)
2562
2562
os.symlink('bar', 'path/foo')
2563
wt.add(['foo'], ['foo-id'])
2564
wt.commit('add symlink', rev_id='A-id')
2563
wt.add(['foo'], [b'foo-id'])
2564
wt.commit('add symlink', rev_id=b'A-id')
2565
2565
os.remove('path/foo')
2566
2566
os.symlink('baz', 'path/foo')
2567
wt.commit('foo => baz', rev_id='B-id')
2568
wt.set_last_revision('A-id')
2569
wt.branch.set_last_revision_info(1, 'A-id')
2567
wt.commit('foo => baz', rev_id=b'B-id')
2568
wt.set_last_revision(b'A-id')
2569
wt.branch.set_last_revision_info(1, b'A-id')
2571
wt.commit('C', rev_id='C-id')
2572
wt.merge_from_branch(wt.branch, 'B-id')
2571
wt.commit('C', rev_id=b'C-id')
2572
wt.merge_from_branch(wt.branch, b'B-id')
2573
2573
self.assertEqual('baz', wt.get_symlink_target('foo'))
2574
wt.commit('E merges C & B', rev_id='E-id')
2574
wt.commit('E merges C & B', rev_id=b'E-id')
2575
2575
os.remove('path/foo')
2576
2576
os.symlink('bing', 'path/foo')
2577
wt.commit('F foo => bing', rev_id='F-id')
2577
wt.commit('F foo => bing', rev_id=b'F-id')
2578
2578
wt.set_last_revision('B-id')
2579
wt.branch.set_last_revision_info(2, 'B-id')
2579
wt.branch.set_last_revision_info(2, b'B-id')
2581
wt.merge_from_branch(wt.branch, 'C-id')
2582
wt.commit('D merges B & C', rev_id='D-id')
2583
wt_base = wt.controldir.sprout('base', 'A-id').open_workingtree()
2581
wt.merge_from_branch(wt.branch, b'C-id')
2582
wt.commit('D merges B & C', rev_id=b'D-id')
2583
wt_base = wt.controldir.sprout('base', b'A-id').open_workingtree()
2584
2584
wt_base.lock_read()
2585
2585
self.addCleanup(wt_base.unlock)
2586
wt_lca1 = wt.controldir.sprout('b-tree', 'B-id').open_workingtree()
2586
wt_lca1 = wt.controldir.sprout('b-tree', b'B-id').open_workingtree()
2587
2587
wt_lca1.lock_read()
2588
2588
self.addCleanup(wt_lca1.unlock)
2589
wt_lca2 = wt.controldir.sprout('c-tree', 'C-id').open_workingtree()
2589
wt_lca2 = wt.controldir.sprout('c-tree', b'C-id').open_workingtree()
2590
2590
wt_lca2.lock_read()
2591
2591
self.addCleanup(wt_lca2.unlock)
2592
wt_other = wt.controldir.sprout('other', 'F-id').open_workingtree()
2592
wt_other = wt.controldir.sprout('other', b'F-id').open_workingtree()
2593
2593
wt_other.lock_read()
2594
2594
self.addCleanup(wt_other.unlock)
2595
2595
merge_obj = _mod_merge.Merge3Merger(wt, wt, wt_base,
2596
2596
wt_other, lca_trees=[wt_lca1, wt_lca2], do_merge=False)
2597
2597
entries = list(merge_obj._entries_lca())
2598
2598
root_id = wt.path2id('')
2599
self.assertEqual([('foo-id', True,
2599
self.assertEqual([(b'foo-id', True,
2600
2600
((root_id, [root_id, root_id]), root_id, root_id),
2601
2601
((u'foo', [u'foo', u'foo']), u'foo', u'foo'),
2602
2602
((False, [False, False]), False, False)),
2614
2614
# F Path at 'foo'
2615
2615
builder = self.get_builder()
2616
2616
builder.build_snapshot(None,
2617
[('add', (u'', 'a-root-id', 'directory', None)),
2618
('add', (u'foo', 'foo-id', 'file', 'a\nb\nc\n'))],
2620
builder.build_snapshot(['A-id'], [], revision_id='C-id')
2621
builder.build_snapshot(['A-id'],
2622
[('rename', ('foo', 'bar'))], revision_id='B-id')
2623
builder.build_snapshot(['C-id', 'B-id'],
2624
[('rename', ('foo', 'bar'))], revision_id='E-id') # merge the rename
2625
builder.build_snapshot(['E-id'],
2626
[('rename', ('bar', 'foo'))], revision_id='F-id') # Rename back to BASE
2627
builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id')
2628
wt, conflicts = self.do_merge(builder, 'F-id')
2617
[('add', (u'', b'a-root-id', 'directory', None)),
2618
('add', (u'foo', b'foo-id', 'file', 'a\nb\nc\n'))],
2619
revision_id=b'A-id')
2620
builder.build_snapshot([b'A-id'], [], revision_id=b'C-id')
2621
builder.build_snapshot([b'A-id'],
2622
[('rename', ('foo', 'bar'))], revision_id=b'B-id')
2623
builder.build_snapshot([b'C-id', b'B-id'],
2624
[('rename', ('foo', 'bar'))], revision_id=b'E-id') # merge the rename
2625
builder.build_snapshot([b'E-id'],
2626
[('rename', ('bar', 'foo'))], revision_id=b'F-id') # Rename back to BASE
2627
builder.build_snapshot([b'B-id', b'C-id'], [], revision_id=b'D-id')
2628
wt, conflicts = self.do_merge(builder, b'F-id')
2629
2629
self.assertEqual(0, conflicts)
2630
self.assertEqual('foo', wt.id2path('foo-id'))
2630
self.assertEqual('foo', wt.id2path(b'foo-id'))
2632
2632
def test_other_reverted_content_to_base(self):
2633
2633
builder = self.get_builder()
2634
2634
builder.build_snapshot(None,
2635
[('add', (u'', 'a-root-id', 'directory', None)),
2636
('add', (u'foo', 'foo-id', 'file', 'base content\n'))],
2635
[('add', (u'', b'a-root-id', 'directory', None)),
2636
('add', (u'foo', b'foo-id', 'file', 'base content\n'))],
2637
2637
revision_id='A-id')
2638
builder.build_snapshot(['A-id'], [], revision_id='C-id')
2639
builder.build_snapshot(['A-id'],
2640
[('modify', ('foo-id', 'B content\n'))],
2642
builder.build_snapshot(['C-id', 'B-id'],
2643
[('modify', ('foo-id', 'B content\n'))],
2644
revision_id='E-id') # merge the content
2645
builder.build_snapshot(['E-id'],
2646
[('modify', ('foo-id', 'base content\n'))],
2647
revision_id='F-id') # Revert back to BASE
2648
builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id')
2649
wt, conflicts = self.do_merge(builder, 'F-id')
2638
builder.build_snapshot([b'A-id'], [], revision_id='C-id')
2639
builder.build_snapshot([b'A-id'],
2640
[('modify', (b'foo-id', 'B content\n'))],
2641
revision_id=b'B-id')
2642
builder.build_snapshot([b'C-id', b'B-id'],
2643
[('modify', (b'foo-id', 'B content\n'))],
2644
revision_id=b'E-id') # merge the content
2645
builder.build_snapshot([b'E-id'],
2646
[('modify', (b'foo-id', 'base content\n'))],
2647
revision_id=b'F-id') # Revert back to BASE
2648
builder.build_snapshot([b'B-id', b'C-id'], [], revision_id=b'D-id')
2649
wt, conflicts = self.do_merge(builder, b'F-id')
2650
2650
self.assertEqual(0, conflicts)
2651
2651
# TODO: We need to use the per-file graph to properly select a BASE
2652
2652
# before this will work. Or at least use the LCA trees to find
2656
2656
def test_other_modified_content(self):
2657
2657
builder = self.get_builder()
2658
2658
builder.build_snapshot(None,
2659
[('add', (u'', 'a-root-id', 'directory', None)),
2660
('add', (u'foo', 'foo-id', 'file', 'base content\n'))],
2662
builder.build_snapshot(['A-id'], [], revision_id='C-id')
2663
builder.build_snapshot(['A-id'],
2664
[('modify', ('foo-id', 'B content\n'))],
2666
builder.build_snapshot(['C-id', 'B-id'],
2667
[('modify', ('foo-id', 'B content\n'))],
2668
revision_id='E-id') # merge the content
2669
builder.build_snapshot(['E-id'],
2670
[('modify', ('foo-id', 'F content\n'))],
2671
revision_id='F-id') # Override B content
2672
builder.build_snapshot(['B-id', 'C-id'], [], revision_id='D-id')
2673
wt, conflicts = self.do_merge(builder, 'F-id')
2659
[('add', (u'', b'a-root-id', 'directory', None)),
2660
('add', (u'foo', b'foo-id', 'file', 'base content\n'))],
2661
revision_id=b'A-id')
2662
builder.build_snapshot([b'A-id'], [], revision_id=b'C-id')
2663
builder.build_snapshot([b'A-id'],
2664
[('modify', (b'foo-id', 'B content\n'))],
2665
revision_id=b'B-id')
2666
builder.build_snapshot([b'C-id', b'B-id'],
2667
[('modify', (b'foo-id', 'B content\n'))],
2668
revision_id=b'E-id') # merge the content
2669
builder.build_snapshot([b'E-id'],
2670
[('modify', (b'foo-id', 'F content\n'))],
2671
revision_id=b'F-id') # Override B content
2672
builder.build_snapshot([b'B-id', b'C-id'], [], revision_id=b'D-id')
2673
wt, conflicts = self.do_merge(builder, b'F-id')
2674
2674
self.assertEqual(0, conflicts)
2675
2675
self.assertEqual('F content\n', wt.get_file_text('foo'))
2738
2738
self.addCleanup(wt.unlock)
2739
2739
sub_tree = self.make_branch_and_tree('tree/sub-tree',
2740
2740
format='development-subtree')
2741
wt.set_root_id('a-root-id')
2742
sub_tree.set_root_id('sub-tree-root')
2743
self.build_tree_contents([('tree/sub-tree/file', 'text1')])
2741
wt.set_root_id(b'a-root-id')
2742
sub_tree.set_root_id(b'sub-tree-root')
2743
self.build_tree_contents([('tree/sub-tree/file', b'text1')])
2744
2744
sub_tree.add('file')
2745
sub_tree.commit('foo', rev_id='sub-A-id')
2745
sub_tree.commit('foo', rev_id=b'sub-A-id')
2746
2746
wt.add_reference(sub_tree)
2747
wt.commit('set text to 1', rev_id='A-id', recursive=None)
2747
wt.commit('set text to 1', rev_id=b'A-id', recursive=None)
2748
2748
# Now create a criss-cross merge in the parent, without modifying the
2750
wt.commit('B', rev_id='B-id', recursive=None)
2750
wt.commit('B', rev_id=b'B-id', recursive=None)
2751
2751
wt.set_last_revision('A-id')
2752
2752
wt.branch.set_last_revision_info(1, 'A-id')
2753
wt.commit('C', rev_id='C-id', recursive=None)
2753
wt.commit('C', rev_id=b'C-id', recursive=None)
2754
2754
wt.merge_from_branch(wt.branch, to_revision='B-id')
2755
wt.commit('E', rev_id='E-id', recursive=None)
2755
wt.commit('E', rev_id=b'E-id', recursive=None)
2756
2756
wt.set_parent_ids(['B-id', 'C-id'])
2757
2757
wt.branch.set_last_revision_info(2, 'B-id')
2758
wt.commit('D', rev_id='D-id', recursive=None)
2758
wt.commit('D', rev_id=b'D-id', recursive=None)
2760
2760
merger = _mod_merge.Merger.from_revision_ids(wt, 'E-id')
2761
2761
merger.merge_type = _mod_merge.Merge3Merger
2772
2772
self.addCleanup(wt.unlock)
2773
2773
sub_tree = self.make_branch_and_tree('tree/sub',
2774
2774
format='development-subtree')
2775
wt.set_root_id('a-root-id')
2776
sub_tree.set_root_id('sub-tree-root')
2777
self.build_tree_contents([('tree/sub/file', 'text1')])
2775
wt.set_root_id(b'a-root-id')
2776
sub_tree.set_root_id(b'sub-tree-root')
2777
self.build_tree_contents([('tree/sub/file', b'text1')])
2778
2778
sub_tree.add('file')
2779
sub_tree.commit('foo', rev_id='sub-A-id')
2779
sub_tree.commit('foo', rev_id=b'sub-A-id')
2780
2780
wt.add_reference(sub_tree)
2781
wt.commit('set text to 1', rev_id='A-id', recursive=None)
2781
wt.commit('set text to 1', rev_id=b'A-id', recursive=None)
2782
2782
# Now create a criss-cross merge in the parent, without modifying the
2784
wt.commit('B', rev_id='B-id', recursive=None)
2784
wt.commit('B', rev_id=b'B-id', recursive=None)
2785
2785
wt.set_last_revision('A-id')
2786
2786
wt.branch.set_last_revision_info(1, 'A-id')
2787
wt.commit('C', rev_id='C-id', recursive=None)
2787
wt.commit('C', rev_id=b'C-id', recursive=None)
2788
2788
wt.merge_from_branch(wt.branch, to_revision='B-id')
2789
self.build_tree_contents([('tree/sub/file', 'text2')])
2790
sub_tree.commit('modify contents', rev_id='sub-B-id')
2791
wt.commit('E', rev_id='E-id', recursive=None)
2789
self.build_tree_contents([('tree/sub/file', b'text2')])
2790
sub_tree.commit('modify contents', rev_id=b'sub-B-id')
2791
wt.commit('E', rev_id=b'E-id', recursive=None)
2792
2792
wt.set_parent_ids(['B-id', 'C-id'])
2793
2793
wt.branch.set_last_revision_info(2, 'B-id')
2794
wt.commit('D', rev_id='D-id', recursive=None)
2794
wt.commit('D', rev_id=b'D-id', recursive=None)
2796
2796
merger = _mod_merge.Merger.from_revision_ids(wt, 'E-id')
2797
2797
merger.merge_type = _mod_merge.Merge3Merger
2810
2810
self.addCleanup(wt.unlock)
2811
2811
sub_tree = self.make_branch_and_tree('tree/sub',
2812
2812
format='development-subtree')
2813
wt.set_root_id('a-root-id')
2814
sub_tree.set_root_id('sub-tree-root')
2815
self.build_tree_contents([('tree/sub/file', 'text1')])
2813
wt.set_root_id(b'a-root-id')
2814
sub_tree.set_root_id(b'sub-tree-root')
2815
self.build_tree_contents([('tree/sub/file', b'text1')])
2816
2816
sub_tree.add('file')
2817
sub_tree.commit('foo', rev_id='sub-A-id')
2817
sub_tree.commit('foo', rev_id=b'sub-A-id')
2818
2818
wt.add_reference(sub_tree)
2819
wt.commit('set text to 1', rev_id='A-id', recursive=None)
2819
wt.commit('set text to 1', rev_id=b'A-id', recursive=None)
2820
2820
# Now create a criss-cross merge in the parent, without modifying the
2822
wt.commit('B', rev_id='B-id', recursive=None)
2822
wt.commit('B', rev_id=b'B-id', recursive=None)
2823
2823
wt.set_last_revision('A-id')
2824
2824
wt.branch.set_last_revision_info(1, 'A-id')
2825
wt.commit('C', rev_id='C-id', recursive=None)
2825
wt.commit('C', rev_id=b'C-id', recursive=None)
2826
2826
wt.merge_from_branch(wt.branch, to_revision='B-id')
2827
2827
wt.rename_one('sub', 'alt_sub')
2828
wt.commit('E', rev_id='E-id', recursive=None)
2828
wt.commit('E', rev_id=b'E-id', recursive=None)
2829
2829
wt.set_last_revision('B-id')
2831
2831
wt.set_parent_ids(['B-id', 'C-id'])
2832
2832
wt.branch.set_last_revision_info(2, 'B-id')
2833
wt.commit('D', rev_id='D-id', recursive=None)
2833
wt.commit('D', rev_id=b'D-id', recursive=None)
2835
2835
merger = _mod_merge.Merger.from_revision_ids(wt, 'E-id')
2836
2836
merger.merge_type = _mod_merge.Merge3Merger
2852
2852
self.addCleanup(wt.unlock)
2853
2853
sub_tree = self.make_branch_and_tree('tree/sub',
2854
2854
format='development-subtree')
2855
wt.set_root_id('a-root-id')
2856
sub_tree.set_root_id('sub-tree-root')
2857
self.build_tree_contents([('tree/sub/file', 'text1')])
2855
wt.set_root_id(b'a-root-id')
2856
sub_tree.set_root_id(b'sub-tree-root')
2857
self.build_tree_contents([('tree/sub/file', b'text1')])
2858
2858
sub_tree.add('file')
2859
sub_tree.commit('foo', rev_id='sub-A-id')
2859
sub_tree.commit('foo', rev_id=b'sub-A-id')
2860
2860
wt.add_reference(sub_tree)
2861
wt.commit('set text to 1', rev_id='A-id', recursive=None)
2861
wt.commit('set text to 1', rev_id=b'A-id', recursive=None)
2862
2862
# Now create a criss-cross merge in the parent, without modifying the
2864
wt.commit('B', rev_id='B-id', recursive=None)
2864
wt.commit('B', rev_id=b'B-id', recursive=None)
2865
2865
wt.set_last_revision('A-id')
2866
2866
wt.branch.set_last_revision_info(1, 'A-id')
2867
wt.commit('C', rev_id='C-id', recursive=None)
2867
wt.commit('C', rev_id=b'C-id', recursive=None)
2868
2868
wt.merge_from_branch(wt.branch, to_revision='B-id')
2869
self.build_tree_contents([('tree/sub/file', 'text2')])
2870
sub_tree.commit('modify contents', rev_id='sub-B-id')
2869
self.build_tree_contents([('tree/sub/file', b'text2')])
2870
sub_tree.commit('modify contents', rev_id=b'sub-B-id')
2871
2871
wt.rename_one('sub', 'alt_sub')
2872
wt.commit('E', rev_id='E-id', recursive=None)
2872
wt.commit('E', rev_id=b'E-id', recursive=None)
2873
2873
wt.set_last_revision('B-id')
2875
2875
wt.set_parent_ids(['B-id', 'C-id'])
2876
2876
wt.branch.set_last_revision_info(2, 'B-id')
2877
wt.commit('D', rev_id='D-id', recursive=None)
2877
wt.commit('D', rev_id=b'D-id', recursive=None)
2879
2879
merger = _mod_merge.Merger.from_revision_ids(wt, 'E-id')
2880
2880
merger.merge_type = _mod_merge.Merge3Merger
3348
3348
def setUp(self):
3349
3349
super(TestMergeHooks, self).setUp()
3350
3350
self.tree_a = self.make_branch_and_tree('tree_a')
3351
self.build_tree_contents([('tree_a/file', 'content_1')])
3352
self.tree_a.add('file', 'file-id')
3351
self.build_tree_contents([('tree_a/file', b'content_1')])
3352
self.tree_a.add('file', b'file-id')
3353
3353
self.tree_a.commit('added file')
3355
3355
self.tree_b = self.tree_a.controldir.sprout('tree_b').open_workingtree()
3356
self.build_tree_contents([('tree_b/file', 'content_2')])
3356
self.build_tree_contents([('tree_b/file', b'content_2')])
3357
3357
self.tree_b.commit('modify file')
3359
3359
def test_pre_merge_hook_inject_different_tree(self):
3360
3360
tree_c = self.tree_b.controldir.sprout('tree_c').open_workingtree()
3361
self.build_tree_contents([('tree_c/file', 'content_3')])
3361
self.build_tree_contents([('tree_c/file', b'content_3')])
3362
3362
tree_c.commit("more content")
3364
3364
def factory(merger):