/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge_core.py

Merge from integration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import os
2
2
import shutil
3
 
import tempfile
4
 
import unittest
5
3
import stat
6
4
import sys
7
5
 
8
 
from bzrlib.selftest import TestCaseInTempDir, TestCase
 
6
from bzrlib.tests import TestCaseInTempDir, TestCase
9
7
from bzrlib.branch import ScratchBranch, Branch
10
8
from bzrlib.errors import (NotBranchError, NotVersionedError,
11
9
                           WorkingTreeNotRevision, BzrCommandError)
12
10
from bzrlib.inventory import RootEntry
13
11
import bzrlib.inventory as inventory
14
 
from bzrlib.osutils import file_kind, rename, sha_file
 
12
from bzrlib.osutils import file_kind, rename, sha_file, pathjoin, mkdtemp
15
13
from bzrlib import changeset
16
14
from bzrlib.merge_core import (ApplyMerge3, make_merge_changeset,
17
15
                               BackupBeforeChange, ExecFlagMerge, WeaveMerge)
64
62
        self.inventory = FalseTree(self)
65
63
    
66
64
    def child_path(self, parent, name):
67
 
        return os.path.join(self.inventory_dict[parent], name)
 
65
        return pathjoin(self.inventory_dict[parent], name)
68
66
 
69
67
    def add_file(self, id, parent, name, contents, mode):
70
68
        path = self.child_path(parent, name)
94
92
        self.inventory_dict[id] = path
95
93
 
96
94
    def abs_path(self, path):
97
 
        return os.path.join(self.dir, path)
 
95
        return pathjoin(self.dir, path)
98
96
 
99
97
    def full_path(self, id):
100
98
        try:
123
121
        return self.full_path(id)
124
122
 
125
123
    def change_path(self, id, path):
126
 
        old_path = os.path.join(self.dir, self.inventory_dict[id])
 
124
        old_path = pathjoin(self.dir, self.inventory_dict[id])
127
125
        rename(old_path, self.abs_path(path))
128
126
        self.inventory_dict[id] = path
129
127
 
140
138
    def get_file_sha1(self, file_id):
141
139
        return sha_file(file(self.full_path(file_id), "rb"))
142
140
 
 
141
 
143
142
class MergeBuilder(object):
144
143
    def __init__(self):
145
 
        self.dir = tempfile.mkdtemp(prefix="BaZing")
146
 
        self.base = MergeTree(os.path.join(self.dir, "base"))
147
 
        self.this = MergeTree(os.path.join(self.dir, "this"))
148
 
        self.other = MergeTree(os.path.join(self.dir, "other"))
 
144
        self.dir = mkdtemp(prefix="BaZing")
 
145
        self.base = MergeTree(pathjoin(self.dir, "base"))
 
146
        self.this = MergeTree(pathjoin(self.dir, "this"))
 
147
        self.other = MergeTree(pathjoin(self.dir, "other"))
149
148
        
150
149
        self.cset = changeset.Changeset()
151
150
        self.cset.add_entry(changeset.ChangesetEntry("0", 
152
151
                                                     changeset.NULL_ID, "./."))
 
152
 
153
153
    def get_cset_path(self, parent, name):
154
154
        if name is None:
155
155
            assert (parent is None)
156
156
            return None
157
 
        return os.path.join(self.cset.entries[parent].path, name)
 
157
        return pathjoin(self.cset.entries[parent].path, name)
158
158
 
159
159
    def add_file(self, id, parent, name, contents, mode):
160
160
        self.base.add_file(id, parent, name, contents, mode)
328
328
                if parent is None:
329
329
                    return orig_inventory[file_id]
330
330
                dirname = new_path(parent)
331
 
                return os.path.join(dirname, orig_inventory[file_id])
 
331
                return pathjoin(dirname, os.path.basename(orig_inventory[file_id]))
332
332
 
333
333
        new_inventory = {}
334
334
        for file_id in orig_inventory.iterkeys():
343
343
            new_inventory[file_id] = path
344
344
        return new_inventory
345
345
 
346
 
    def apply_changeset(self, cset, conflict_handler=None, reverse=False):
 
346
    def apply_changeset(self, cset, conflict_handler=None):
347
347
        inventory_change = changeset.apply_changeset(cset,
348
348
                                                     self.this.inventory_dict,
349
349
                                                     self.this.dir,
350
 
                                                     conflict_handler, reverse)
 
350
                                                     conflict_handler)
351
351
        self.this.inventory_dict =  self.apply_inv_change(inventory_change, 
352
352
                                                     self.this.inventory_dict)
353
353
 
355
355
        shutil.rmtree(self.dir)
356
356
 
357
357
 
358
 
class MergeTest(unittest.TestCase):
 
358
class MergeTest(TestCase):
359
359
    def test_change_name(self):
360
360
        """Test renames"""
361
361
        builder = MergeBuilder()
366
366
        builder.add_file("3", "0", "name5", "hello3", 0755)
367
367
        builder.change_name("3", this="name6")
368
368
        cset = builder.merge_changeset(ApplyMerge3)
369
 
        self.assert_(cset.entries["2"].is_boring())
370
 
        self.assert_(cset.entries["1"].name == "name1")
371
 
        self.assert_(cset.entries["1"].new_name == "name2")
372
 
        self.assert_(cset.entries["3"].is_boring())
 
369
        self.failUnless(cset.entries["2"].is_boring())
 
370
        self.assertEqual(cset.entries["1"].name, "name1")
 
371
        self.assertEqual(cset.entries["1"].new_name, "name2")
 
372
        self.failUnless(cset.entries["3"].is_boring())
373
373
        for tree in (builder.this, builder.other, builder.base):
374
 
            self.assert_(tree.dir != builder.dir and 
375
 
                   tree.dir.startswith(builder.dir))
 
374
            self.assertNotEqual(tree.dir, builder.dir)
 
375
            self.assertStartsWith(tree.dir, builder.dir)
376
376
            for path in tree.inventory_dict.itervalues():
377
377
                fullpath = tree.abs_path(path)
378
 
                self.assert_(fullpath.startswith(tree.dir))
379
 
                self.assert_(not path.startswith(tree.dir))
380
 
                self.assert_(os.path.exists(fullpath))
 
378
                self.assertStartsWith(fullpath, tree.dir)
 
379
                self.failIf(path.startswith(tree.dir))
 
380
                self.failUnless(os.path.lexists(fullpath))
381
381
        builder.apply_changeset(cset)
382
382
        builder.cleanup()
383
383
        builder = MergeBuilder()
536
536
 
537
537
    def test_trivial_star_merge(self):
538
538
        """Test that merges in a star shape Just Work.""" 
539
 
        from bzrlib.add import smart_add_tree, add_reporter_null
 
539
        from bzrlib.add import smart_add_tree
540
540
        from bzrlib.clone import copy_branch
541
541
        from bzrlib.merge import merge
542
542
        # John starts a branch
543
543
        self.build_tree(("original/", "original/file1", "original/file2"))
544
544
        branch = Branch.initialize("original")
545
545
        tree = WorkingTree('original', branch)
546
 
        smart_add_tree(tree, ["original"], True, add_reporter_null)
 
546
        smart_add_tree(tree, ["original"])
547
547
        tree.commit("start branch.", verbose=False)
548
548
        # Mary branches it.
549
549
        self.build_tree(("mary/",))
634
634
        self.assert_(os.path.lexists('a/file.moved'))
635
635
        self.assertEqual(a.working_tree().pending_merges(), [b.last_revision()])
636
636
 
 
637
    def test_merge_deleted_conflicts(self):
 
638
        os.mkdir('a')
 
639
        a = Branch.initialize('a')
 
640
        file('a/file', 'wb').write('contents\n')
 
641
        a.working_tree().add('file')
 
642
        a.working_tree().commit('a_revision', allow_pointless=False)
 
643
        del a
 
644
        self.run_bzr('branch', 'a', 'b')
 
645
        a = Branch.open('a')
 
646
        os.remove('a/file')
 
647
        a.working_tree().commit('removed file', allow_pointless=False)
 
648
        file('b/file', 'wb').write('changed contents\n')
 
649
        b = Branch.open('b')
 
650
        b.working_tree().commit('changed file', allow_pointless=False)
 
651
        merge(['a', -1], ['a', 1], this_dir='b')
 
652
        self.failIf(os.path.lexists('b/file'))
 
653
 
637
654
    def test_merge_metadata_vs_deletion(self):
638
655
        """Conflict deletion vs metadata change"""
639
656
        os.mkdir('a')
653
670
        b_wt.commit('exec a')
654
671
        merge(['b', -1], ['b', 0], this_dir='a')
655
672
        self.assert_(os.path.exists('a/file'))
 
673
 
 
674
    def test_merge_swapping_renames(self):
 
675
        os.mkdir('a')
 
676
        a = Branch.initialize('a')
 
677
        file('a/un','wb').write('UN')
 
678
        file('a/deux','wb').write('DEUX')
 
679
        a_wt = a.working_tree()
 
680
        a_wt.add('un')
 
681
        a_wt.add('deux')
 
682
        a_wt.commit('r0')
 
683
        copy_branch(a,'b')
 
684
        b = Branch.open('b')
 
685
        b_wt = b.working_tree()
 
686
        b_wt.rename_one('un','tmp')
 
687
        b_wt.rename_one('deux','un')
 
688
        b_wt.rename_one('tmp','deux')
 
689
        b_wt.commit('r1')
 
690
        merge(['b', -1],['b', 1],this_dir='a')
 
691
        self.assert_(os.path.exists('a/un'))
 
692
        self.assert_(os.path.exists('a/deux'))
 
693
        self.assertFalse(os.path.exists('a/tmp'))
 
694
        self.assertEqual(file('a/un').read(),'DEUX')
 
695
        self.assertEqual(file('a/deux').read(),'UN')
 
696
 
 
697
    def test_merge_delete_and_add_same(self):
 
698
        os.mkdir('a')
 
699
        a = Branch.initialize('a')
 
700
        file('a/file', 'wb').write('THIS')
 
701
        a_wt = a.working_tree()
 
702
        a_wt.add('file')
 
703
        a_wt.commit('r0')
 
704
        copy_branch(a, 'b')
 
705
        b = Branch.open('b')
 
706
        b_wt = b.working_tree()
 
707
        os.remove('b/file')
 
708
        b_wt.commit('r1')
 
709
        file('b/file', 'wb').write('THAT')
 
710
        b_wt.add('file')
 
711
        b_wt.commit('r2')
 
712
        merge(['b', -1],['b', 1],this_dir='a')
 
713
        self.assert_(os.path.exists('a/file'))
 
714
        self.assertEqual(file('a/file').read(),'THAT')
 
715
 
 
716
    def test_merge_rename_before_create(self):
 
717
        """rename before create
 
718
        
 
719
        This case requires that you must not do creates
 
720
        before move-into-place:
 
721
 
 
722
        $ touch foo
 
723
        $ bzr add foo
 
724
        $ bzr commit
 
725
        $ bzr mv foo bar
 
726
        $ touch foo
 
727
        $ bzr add foo
 
728
        $ bzr commit
 
729
        """
 
730
        os.mkdir('a')
 
731
        a = Branch.initialize('a')
 
732
        file('a/foo', 'wb').write('A/FOO')
 
733
        a_wt = a.working_tree()
 
734
        a_wt.add('foo')
 
735
        a_wt.commit('added foo')
 
736
        copy_branch(a, 'b')
 
737
        b = Branch.open('b')
 
738
        b_wt = b.working_tree()
 
739
        b_wt.rename_one('foo', 'bar')
 
740
        file('b/foo', 'wb').write('B/FOO')
 
741
        b_wt.add('foo')
 
742
        b_wt.commit('moved foo to bar, added new foo')
 
743
        merge(['b', -1],['b', 1],this_dir='a')
 
744
 
 
745
    def test_merge_create_before_rename(self):
 
746
        """create before rename, target parents before children
 
747
 
 
748
        This case requires that you must not do move-into-place
 
749
        before creates, and that you must not do children after
 
750
        parents:
 
751
 
 
752
        $ touch foo
 
753
        $ bzr add foo
 
754
        $ bzr commit
 
755
        $ bzr mkdir bar
 
756
        $ bzr add bar
 
757
        $ bzr mv foo bar/foo
 
758
        $ bzr commit
 
759
        """
 
760
        os.mkdir('a')
 
761
        a = Branch.initialize('a')
 
762
        file('a/foo', 'wb').write('A/FOO')
 
763
        a_wt = a.working_tree()
 
764
        a_wt.add('foo')
 
765
        a_wt.commit('added foo')
 
766
        copy_branch(a, 'b')
 
767
        b = Branch.open('b')
 
768
        b_wt = b.working_tree()
 
769
        os.mkdir('b/bar')
 
770
        b_wt.add('bar')
 
771
        b_wt.rename_one('foo', 'bar/foo')
 
772
        b_wt.commit('created bar dir, moved foo into bar')
 
773
        merge(['b', -1],['b', 1],this_dir='a')
 
774
 
 
775
    def test_merge_rename_to_temp_before_delete(self):
 
776
        """rename to temp before delete, source children before parents
 
777
 
 
778
        This case requires that you must not do deletes before
 
779
        move-out-of-the-way, and that you must not do children
 
780
        after parents:
 
781
        
 
782
        $ mkdir foo
 
783
        $ touch foo/bar
 
784
        $ bzr add foo/bar
 
785
        $ bzr commit
 
786
        $ bzr mv foo/bar bar
 
787
        $ rmdir foo
 
788
        $ bzr commit
 
789
        """
 
790
        os.mkdir('a')
 
791
        a = Branch.initialize('a')
 
792
        os.mkdir('a/foo')
 
793
        file('a/foo/bar', 'wb').write('A/FOO/BAR')
 
794
        a_wt = a.working_tree()
 
795
        a_wt.add('foo')
 
796
        a_wt.add('foo/bar')
 
797
        a_wt.commit('added foo/bar')
 
798
        copy_branch(a, 'b')
 
799
        b = Branch.open('b')
 
800
        b_wt = b.working_tree()
 
801
        b_wt.rename_one('foo/bar', 'bar')
 
802
        os.rmdir('b/foo')
 
803
        b_wt.remove('foo')
 
804
        b_wt.commit('moved foo/bar to bar, deleted foo')
 
805
        merge(['b', -1],['b', 1],this_dir='a')
 
806
 
 
807
    def test_merge_delete_before_rename_to_temp(self):
 
808
        """delete before rename to temp
 
809
 
 
810
        This case requires that you must not do
 
811
        move-out-of-the-way before deletes:
 
812
        
 
813
        $ touch foo
 
814
        $ touch bar
 
815
        $ bzr add foo bar
 
816
        $ bzr commit
 
817
        $ rm foo
 
818
        $ bzr rm foo
 
819
        $ bzr mv bar foo
 
820
        $ bzr commit
 
821
        """
 
822
        os.mkdir('a')
 
823
        a = Branch.initialize('a')
 
824
        file('a/foo', 'wb').write('A/FOO')
 
825
        file('a/bar', 'wb').write('A/BAR')
 
826
        a_wt = a.working_tree()
 
827
        a_wt.add('foo')
 
828
        a_wt.add('bar')
 
829
        a_wt.commit('added foo and bar')
 
830
        copy_branch(a, 'b')
 
831
        b = Branch.open('b')
 
832
        b_wt = b.working_tree()
 
833
        os.unlink('b/foo')
 
834
        b_wt.remove('foo')
 
835
        b_wt.rename_one('bar', 'foo')
 
836
        b_wt.commit('deleted foo, renamed bar to foo')
 
837
        merge(['b', -1],['b', 1],this_dir='a')
 
838