1
# Copyright (C) 2005-2010 Canonical Ltd
1
# Copyright (C) 2005-2011 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
34
39
from bzrlib.osutils import getcwd, pathjoin
35
from bzrlib import progress
36
40
from bzrlib.transform import TreeTransform
37
41
from bzrlib.tests import TestCaseWithTransport, TestSkipped
38
42
from bzrlib.workingtree import WorkingTree
41
45
class MergeBuilder(object):
42
47
def __init__(self, dir=None):
43
48
self.dir = osutils.mkdtemp(prefix="merge-test", dir=dir)
44
49
self.tree_root = generate_ids.gen_root_id()
46
51
path = pathjoin(self.dir, name)
48
wt = bzrlib.bzrdir.BzrDir.create_standalone_workingtree(path)
53
wt = controldir.ControlDir.create_standalone_workingtree(path)
49
54
# the tests perform pulls, so need a branch that is writeable.
51
56
wt.set_root_id(self.tree_root)
96
101
wt.commit('branch commit')
98
if len(wt.branch.revision_history()) != 2:
103
if wt.branch.last_revision_info()[0] != 2:
99
104
raise AssertionError()
100
105
self.this.branch.fetch(self.other.branch)
101
106
other_basis = self.other.branch.basis_tree()
490
495
wtb = d_b.open_workingtree()
491
496
wtb.commit('this revision', allow_pointless=False)
492
497
self.assertEqual(1, wtb.merge_from_branch(wta.branch))
493
self.failUnlessExists('b/file.THIS')
494
self.failUnlessExists('b/file.BASE')
495
self.failUnlessExists('b/file.OTHER')
498
self.assertPathExists('b/file.THIS')
499
self.assertPathExists('b/file.BASE')
500
self.assertPathExists('b/file.OTHER')
497
502
self.assertEqual(1, wtb.merge_from_branch(wta.branch,
498
503
merge_type=WeaveMerger))
499
self.failUnlessExists('b/file')
500
self.failUnlessExists('b/file.THIS')
501
self.failUnlessExists('b/file.BASE')
502
self.failUnlessExists('b/file.OTHER')
504
self.assertPathExists('b/file')
505
self.assertPathExists('b/file.THIS')
506
self.assertPathExists('b/file.BASE')
507
self.assertPathExists('b/file.OTHER')
504
509
def test_weave_conflicts_not_in_base(self):
505
510
builder = self.make_branch_builder('source')
529
534
self.assertEqual(1, tree.merge_from_branch(tree.branch,
530
535
to_revision='D-id',
531
536
merge_type=WeaveMerger))
532
self.failUnlessExists('tree/foo.THIS')
533
self.failUnlessExists('tree/foo.OTHER')
537
self.assertPathExists('tree/foo.THIS')
538
self.assertPathExists('tree/foo.OTHER')
534
539
self.expectFailure('fail to create .BASE in some criss-cross merges',
535
self.failUnlessExists, 'tree/foo.BASE')
536
self.failUnlessExists('tree/foo.BASE')
540
self.assertPathExists, 'tree/foo.BASE')
541
self.assertPathExists('tree/foo.BASE')
538
543
def test_merge_unrelated(self):
539
544
"""Sucessfully merges unrelated branches with no common names"""
540
545
wta = self.make_branch_and_tree('a')
542
file('a/a_file', 'wb').write('contents\n')
547
with file('a/a_file', 'wb') as f: f.write('contents\n')
543
548
wta.add('a_file')
544
549
wta.commit('a_revision', allow_pointless=False)
545
550
wtb = self.make_branch_and_tree('b')
547
file('b/b_file', 'wb').write('contents\n')
552
with file('b/b_file', 'wb') as f: f.write('contents\n')
548
553
wtb.add('b_file')
549
554
b_rev = wtb.commit('b_revision', allow_pointless=False)
550
555
wta.merge_from_branch(wtb.branch, b_rev, 'null:')
555
560
"""Sucessfully merges unrelated branches with common names"""
556
561
wta = self.make_branch_and_tree('a')
558
file('a/file', 'wb').write('contents\n')
563
with file('a/file', 'wb') as f: f.write('contents\n')
560
565
wta.commit('a_revision', allow_pointless=False)
561
566
wtb = self.make_branch_and_tree('b')
563
file('b/file', 'wb').write('contents\n')
568
with file('b/file', 'wb') as f: f.write('contents\n')
565
570
b_rev = wtb.commit('b_revision', allow_pointless=False)
566
571
wta.merge_from_branch(wtb.branch, b_rev, 'null:')
571
576
def test_merge_deleted_conflicts(self):
572
577
wta = self.make_branch_and_tree('a')
573
file('a/file', 'wb').write('contents\n')
578
with file('a/file', 'wb') as f: f.write('contents\n')
575
580
wta.commit('a_revision', allow_pointless=False)
576
581
self.run_bzr('branch a b')
577
582
os.remove('a/file')
578
583
wta.commit('removed file', allow_pointless=False)
579
file('b/file', 'wb').write('changed contents\n')
584
with file('b/file', 'wb') as f: f.write('changed contents\n')
580
585
wtb = WorkingTree.open('b')
581
586
wtb.commit('changed file', allow_pointless=False)
582
587
wtb.merge_from_branch(wta.branch, wta.branch.last_revision(),
583
588
wta.branch.get_rev_id(1))
584
self.failIf(os.path.lexists('b/file'))
589
self.assertFalse(os.path.lexists('b/file'))
586
591
def test_merge_metadata_vs_deletion(self):
587
592
"""Conflict deletion vs metadata change"""
588
593
a_wt = self.make_branch_and_tree('a')
589
file('a/file', 'wb').write('contents\n')
594
with file('a/file', 'wb') as f: f.write('contents\n')
591
596
a_wt.commit('r0')
592
597
self.run_bzr('branch a b')
603
608
def test_merge_swapping_renames(self):
604
609
a_wt = self.make_branch_and_tree('a')
605
file('a/un','wb').write('UN')
606
file('a/deux','wb').write('DEUX')
610
with file('a/un','wb') as f: f.write('UN')
611
with file('a/deux','wb') as f: f.write('DEUX')
607
612
a_wt.add('un', 'un-id')
608
613
a_wt.add('deux', 'deux-id')
609
614
a_wt.commit('r0', rev_id='r0')
615
620
b_wt.commit('r1', rev_id='r1')
616
621
self.assertEqual(0, a_wt.merge_from_branch(b_wt.branch,
617
622
b_wt.branch.last_revision(), b_wt.branch.get_rev_id(1)))
618
self.failUnlessExists('a/un')
619
self.failUnless('a/deux')
623
self.assertPathExists('a/un')
624
self.assertTrue('a/deux')
620
625
self.assertFalse(os.path.exists('a/tmp'))
621
626
self.assertEqual(file('a/un').read(),'DEUX')
622
627
self.assertEqual(file('a/deux').read(),'UN')
624
629
def test_merge_delete_and_add_same(self):
625
630
a_wt = self.make_branch_and_tree('a')
626
file('a/file', 'wb').write('THIS')
631
with file('a/file', 'wb') as f: f.write('THIS')
628
633
a_wt.commit('r0')
629
634
self.run_bzr('branch a b')
630
635
b_wt = WorkingTree.open('b')
631
636
os.remove('b/file')
632
637
b_wt.commit('r1')
633
file('b/file', 'wb').write('THAT')
638
with file('b/file', 'wb') as f: f.write('THAT')
635
640
b_wt.commit('r2')
636
641
a_wt.merge_from_branch(b_wt.branch, b_wt.branch.last_revision(),
655
660
a_wt = self.make_branch_and_tree('a')
656
file('a/foo', 'wb').write('A/FOO')
661
with file('a/foo', 'wb') as f: f.write('A/FOO')
658
663
a_wt.commit('added foo')
659
664
self.run_bzr('branch a b')
660
665
b_wt = WorkingTree.open('b')
661
666
b_wt.rename_one('foo', 'bar')
662
file('b/foo', 'wb').write('B/FOO')
667
with file('b/foo', 'wb') as f: f.write('B/FOO')
664
669
b_wt.commit('moved foo to bar, added new foo')
665
670
a_wt.merge_from_branch(b_wt.branch, b_wt.branch.last_revision(),
684
689
a_wt = self.make_branch_and_tree('a')
685
file('a/foo', 'wb').write('A/FOO')
690
with file('a/foo', 'wb') as f: f.write('A/FOO')
687
692
a_wt.commit('added foo')
688
693
self.run_bzr('branch a b')
712
717
a_wt = self.make_branch_and_tree('a')
713
718
os.mkdir('a/foo')
714
file('a/foo/bar', 'wb').write('A/FOO/BAR')
719
with file('a/foo/bar', 'wb') as f: f.write('A/FOO/BAR')
716
721
a_wt.add('foo/bar')
717
722
a_wt.commit('added foo/bar')
742
747
a_wt = self.make_branch_and_tree('a')
743
file('a/foo', 'wb').write('A/FOO')
744
file('a/bar', 'wb').write('A/BAR')
748
with file('a/foo', 'wb') as f: f.write('A/FOO')
749
with file('a/bar', 'wb') as f: f.write('A/BAR')
747
752
a_wt.commit('added foo and bar')