~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testrevision.py

merge merge tweaks from aaron, which includes latest .dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
 
18
 
import os
19
 
import warnings
20
 
 
21
 
from bzrlib.branch import Branch
22
 
from bzrlib.errors import NoSuchRevision
23
 
from bzrlib.commit import commit
24
 
from bzrlib.graph import Graph
25
 
from bzrlib.revision import (find_present_ancestors, combined_graph,
26
 
                             common_ancestor,
27
 
                             is_ancestor, MultipleRevisionSources)
28
 
from bzrlib.tests import TestCaseWithTransport
29
 
from bzrlib.trace import mutter
30
 
from bzrlib.workingtree import WorkingTree
31
 
 
32
 
# We're allowed to test deprecated interfaces
33
 
warnings.filterwarnings('ignore',
34
 
        '.*get_intervening_revisions was deprecated',
35
 
        DeprecationWarning,
36
 
        r'bzrlib\.tests\.test_revision')
37
 
 
38
 
# XXX: Make this a method of a merge base case
39
 
def make_branches(self):
40
 
    """Create two branches
41
 
 
42
 
    branch 1 has 6 commits, branch 2 has 3 commits
43
 
    commit 10 is a ghosted merge merge from branch 1
44
 
 
45
 
    the object graph is
46
 
    B:     A:
47
 
    a..0   a..0 
48
 
    a..1   a..1
49
 
    a..2   a..2
50
 
    b..3   a..3 merges b..4
51
 
    b..4   a..4
52
 
    b..5   a..5 merges b..5
53
 
    b..6 merges a4
54
 
 
55
 
    so A is missing b6 at the start
56
 
    and B is missing a3, a4, a5
57
 
    """
58
 
    tree1 = self.make_branch_and_tree("branch1")
59
 
    br1 = tree1.branch
 
17
from bzrlib.selftest import TestCaseInTempDir
 
18
 
 
19
 
 
20
def make_branches():
 
21
    from bzrlib.branch import Branch
 
22
    from bzrlib.commit import commit
 
23
    import os
 
24
    os.mkdir("branch1")
 
25
    br1 = Branch.initialize("branch1")
60
26
    
61
 
    tree1.commit("Commit one", rev_id="a@u-0-0")
62
 
    tree1.commit("Commit two", rev_id="a@u-0-1")
63
 
    tree1.commit("Commit three", rev_id="a@u-0-2")
 
27
    commit(br1, "Commit one", rev_id="a@u-0-0")
 
28
    commit(br1, "Commit two", rev_id="a@u-0-1")
 
29
    commit(br1, "Commit three", rev_id="a@u-0-2")
64
30
 
65
 
    tree2 = tree1.bzrdir.clone("branch2").open_workingtree()
66
 
    br2 = tree2.branch
67
 
    tree2.commit("Commit four", rev_id="b@u-0-3")
68
 
    tree2.commit("Commit five", rev_id="b@u-0-4")
 
31
    os.mkdir("branch2")
 
32
    br2 = Branch.initialize("branch2")
 
33
    br2.update_revisions(br1)
 
34
    commit(br2, "Commit four", rev_id="b@u-0-3")
 
35
    commit(br2, "Commit five", rev_id="b@u-0-4")
69
36
    revisions_2 = br2.revision_history()
70
 
    
71
 
    br1.fetch(br2)
72
 
    tree1.add_pending_merge(revisions_2[4])
73
 
    self.assertEquals(revisions_2[4], 'b@u-0-4')
74
 
    tree1.commit("Commit six", rev_id="a@u-0-3")
75
 
    tree1.commit("Commit seven", rev_id="a@u-0-4")
76
 
    tree2.commit("Commit eight", rev_id="b@u-0-5")
77
 
    
78
 
    br1.fetch(br2)
79
 
    tree1.add_pending_merge(br2.revision_history()[5])
80
 
    tree1.commit("Commit nine", rev_id="a@u-0-5")
81
 
    # DO NOT FETCH HERE - we WANT a GHOST.
82
 
    # br2.fetch(br1)
83
 
    tree2.add_pending_merge(br1.revision_history()[4])
84
 
    tree2.commit("Commit ten - ghost merge", rev_id="b@u-0-6")
85
 
    
 
37
    br1.add_pending_merge(revisions_2[4])
 
38
    commit(br1, "Commit six", rev_id="a@u-0-3")
 
39
    commit(br1, "Commit seven", rev_id="a@u-0-4")
 
40
    commit(br2, "Commit eight", rev_id="b@u-0-5")
 
41
    br1.add_pending_merge(br2.revision_history()[5])
 
42
    commit(br1, "Commit nine", rev_id="a@u-0-5")
 
43
    br2.add_pending_merge(br1.revision_history()[4])
 
44
    commit(br2, "Commit ten", rev_id="b@u-0-6")
86
45
    return br1, br2
87
46
 
88
47
 
89
 
class TestIsAncestor(TestCaseWithTransport):
90
 
 
91
 
    def test_recorded_ancestry(self):
92
 
        """Test that commit records all ancestors"""
93
 
        br1, br2 = make_branches(self)
94
 
        d = [('a@u-0-0', ['a@u-0-0']),
95
 
             ('a@u-0-1', ['a@u-0-0', 'a@u-0-1']),
96
 
             ('a@u-0-2', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2']),
97
 
             ('b@u-0-3', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3']),
98
 
             ('b@u-0-4', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3',
99
 
                          'b@u-0-4']),
100
 
             ('a@u-0-3', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4',
101
 
                          'a@u-0-3']),
102
 
             ('a@u-0-4', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4',
103
 
                          'a@u-0-3', 'a@u-0-4']),
104
 
             ('b@u-0-5', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4',
105
 
                          'b@u-0-5']),
106
 
             ('a@u-0-5', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4',
107
 
                          'b@u-0-3', 'b@u-0-4',
108
 
                          'b@u-0-5', 'a@u-0-5']),
109
 
             ('b@u-0-6', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2',
110
 
                          'b@u-0-3', 'b@u-0-4',
111
 
                          'b@u-0-5', 'b@u-0-6']),
112
 
             ]
113
 
        br1_only = ('a@u-0-3', 'a@u-0-4', 'a@u-0-5')
114
 
        br2_only = ('b@u-0-6',)
115
 
        for branch in br1, br2:
116
 
            for rev_id, anc in d:
117
 
                if rev_id in br1_only and not branch is br1:
118
 
                    continue
119
 
                if rev_id in br2_only and not branch is br2:
120
 
                    continue
121
 
                mutter('ancestry of {%s}: %r',
122
 
                       rev_id, branch.repository.get_ancestry(rev_id))
123
 
                result = sorted(branch.repository.get_ancestry(rev_id))
124
 
                self.assertEquals(result, [None] + sorted(anc))
125
 
    
126
 
    
 
48
class TestIsAncestor(TestCaseInTempDir):
127
49
    def test_is_ancestor(self):
128
50
        """Test checking whether a revision is an ancestor of another revision"""
129
 
        br1, br2 = make_branches(self)
 
51
        from bzrlib.revision import is_ancestor, MultipleRevisionSources
 
52
        from bzrlib.errors import NoSuchRevision
 
53
        br1, br2 = make_branches()
130
54
        revisions = br1.revision_history()
131
55
        revisions_2 = br2.revision_history()
132
 
        sources = br1
133
 
 
134
 
        self.assert_(is_ancestor(revisions[0], revisions[0], br1))
135
 
        self.assert_(is_ancestor(revisions[1], revisions[0], sources))
136
 
        self.assert_(not is_ancestor(revisions[0], revisions[1], sources))
137
 
        self.assert_(is_ancestor(revisions_2[3], revisions[0], sources))
138
 
        # disabled mbp 20050914, doesn't seem to happen anymore
139
 
        ## self.assertRaises(NoSuchRevision, is_ancestor, revisions_2[3],
140
 
        ##                  revisions[0], br1)        
141
 
        self.assert_(is_ancestor(revisions[3], revisions_2[4], sources))
142
 
        self.assert_(is_ancestor(revisions[3], revisions_2[4], br1))
143
 
        self.assert_(is_ancestor(revisions[3], revisions_2[3], sources))
144
 
        ## self.assert_(not is_ancestor(revisions[3], revisions_2[3], br1))
145
 
 
146
 
 
147
 
class TestIntermediateRevisions(TestCaseWithTransport):
148
 
 
149
 
    def setUp(self):
150
 
        from bzrlib.commit import commit
151
 
        TestCaseWithTransport.setUp(self)
152
 
        self.br1, self.br2 = make_branches(self)
153
 
        wt1 = self.br1.bzrdir.open_workingtree()
154
 
        wt2 = self.br2.bzrdir.open_workingtree()
155
 
        wt2.commit("Commit eleven", rev_id="b@u-0-7")
156
 
        wt2.commit("Commit twelve", rev_id="b@u-0-8")
157
 
        wt2.commit("Commit thirtteen", rev_id="b@u-0-9")
158
 
 
159
 
        self.br1.fetch(self.br2)
160
 
        wt1.add_pending_merge(self.br2.revision_history()[6])
161
 
        wt1.commit("Commit fourtten", rev_id="a@u-0-6")
162
 
 
163
 
        self.br2.fetch(self.br1)
164
 
        wt2.add_pending_merge(self.br1.revision_history()[6])
165
 
        wt2.commit("Commit fifteen", rev_id="b@u-0-10")
166
 
 
167
 
        from bzrlib.revision import MultipleRevisionSources
168
 
        self.sources = MultipleRevisionSources(self.br1.repository,
169
 
                                               self.br2.repository)
170
 
 
171
 
 
172
 
 
173
 
class MockRevisionSource(object):
174
 
    """A RevisionSource that takes a pregenerated graph.
175
 
 
176
 
    This is useful for testing revision graph algorithms where
177
 
    the actual branch existing is irrelevant.
178
 
    """
179
 
 
180
 
    def __init__(self, full_graph):
181
 
        self._full_graph = full_graph
182
 
 
183
 
    def get_revision_graph_with_ghosts(self, revision_ids):
184
 
        # This is mocked out to just return a constant graph.
185
 
        return self._full_graph
186
 
 
187
 
 
188
 
class TestCommonAncestor(TestCaseWithTransport):
 
56
        sources = MultipleRevisionSources(br1, br2)
 
57
 
 
58
        assert is_ancestor(revisions[0], revisions[0], sources)
 
59
        assert is_ancestor(revisions[1], revisions[0], sources)
 
60
        assert not is_ancestor(revisions[0], revisions[1], sources)
 
61
        assert is_ancestor(revisions_2[3], revisions[0], sources)
 
62
        self.assertRaises(NoSuchRevision, is_ancestor, revisions_2[3],
 
63
                          revisions[0], br1)        
 
64
        assert is_ancestor(revisions[3], revisions_2[4], sources)
 
65
        assert is_ancestor(revisions[3], revisions_2[4], br1)
 
66
        assert is_ancestor(revisions[3], revisions_2[3], sources)
 
67
        assert not is_ancestor(revisions[3], revisions_2[3], br1)
 
68
 
 
69
class TestIntermediateRevisions(TestCaseInTempDir):
 
70
 
 
71
    def setUp(self):
 
72
        from bzrlib.commit import commit
 
73
        TestCaseInTempDir.setUp(self)
 
74
        self.br1, self.br2 = make_branches()
 
75
        commit(self.br2, "Commit eleven", rev_id="b@u-0-7")
 
76
        commit(self.br2, "Commit twelve", rev_id="b@u-0-8")
 
77
        commit(self.br2, "Commit thirtteen", rev_id="b@u-0-9")
 
78
        self.br1.add_pending_merge(self.br2.revision_history()[6])
 
79
        commit(self.br1, "Commit fourtten", rev_id="a@u-0-6")
 
80
        self.br2.add_pending_merge(self.br1.revision_history()[6])
 
81
        commit(self.br2, "Commit fifteen", rev_id="b@u-0-10")
 
82
 
 
83
        from bzrlib.revision import MultipleRevisionSources
 
84
        self.sources = MultipleRevisionSources(self.br1, self.br2)
 
85
 
 
86
    def intervene(self, ancestor, revision, revision_history=None):
 
87
        from bzrlib.revision import get_intervening_revisions
 
88
        return get_intervening_revisions(ancestor,revision, self.sources, 
 
89
                                         revision_history)
 
90
 
 
91
    def test_intervene(self):
 
92
        """Find intermediate revisions, without requiring history"""
 
93
        from bzrlib.errors import NotAncestor, NoSuchRevision
 
94
        assert len(self.intervene('a@u-0-0', 'a@u-0-0')) == 0
 
95
        self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-1'), ['a@u-0-1'])
 
96
        self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-2'), 
 
97
                         ['a@u-0-1', 'a@u-0-2'])
 
98
        self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-3'), 
 
99
                         ['a@u-0-1', 'a@u-0-2', 'b@u-0-3'])
 
100
        self.assertEqual(self.intervene('b@u-0-3', 'a@u-0-3'), 
 
101
                         ['b@u-0-4', 'a@u-0-3'])
 
102
        self.assertEqual(self.intervene('a@u-0-2', 'a@u-0-3', 
 
103
                                        self.br1.revision_history()), 
 
104
                         ['a@u-0-3'])
 
105
        self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-5', 
 
106
                                        self.br1.revision_history()), 
 
107
                         ['a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4', 
 
108
                          'a@u-0-5'])
 
109
        self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-6', 
 
110
                         self.br1.revision_history()), 
 
111
                         ['a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4', 
 
112
                          'b@u-0-6'])
 
113
        self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-5'), 
 
114
                         ['a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4', 
 
115
                          'b@u-0-5'])
 
116
        self.assertEqual(self.intervene('b@u-0-3', 'b@u-0-6', 
 
117
                         self.br2.revision_history()), 
 
118
                         ['b@u-0-4', 'b@u-0-5', 'b@u-0-6'])
 
119
        self.assertEqual(self.intervene('b@u-0-6', 'b@u-0-10'), 
 
120
                         ['b@u-0-7', 'b@u-0-8', 'b@u-0-9', 'b@u-0-10'])
 
121
        self.assertEqual(self.intervene('b@u-0-6', 'b@u-0-10', 
 
122
                                        self.br2.revision_history()), 
 
123
                         ['b@u-0-7', 'b@u-0-8', 'b@u-0-9', 'b@u-0-10'])
 
124
        self.assertRaises(NotAncestor, self.intervene, 'b@u-0-10', 'b@u-0-6', 
 
125
                          self.br2.revision_history())
 
126
        self.assertRaises(NoSuchRevision, self.intervene, 'c@u-0-10', 
 
127
                          'b@u-0-6', self.br2.revision_history())
 
128
        self.assertRaises(NoSuchRevision, self.intervene, 'b@u-0-10', 
 
129
                          'c@u-0-6', self.br2.revision_history())
 
130
 
 
131
class TestIntermediateRevisions(TestCaseInTempDir):
 
132
 
 
133
    def setUp(self):
 
134
        from bzrlib.commit import commit
 
135
        TestCaseInTempDir.setUp(self)
 
136
        self.br1, self.br2 = make_branches()
 
137
        commit(self.br2, "Commit eleven", rev_id="b@u-0-7")
 
138
        commit(self.br2, "Commit twelve", rev_id="b@u-0-8")
 
139
        commit(self.br2, "Commit thirtteen", rev_id="b@u-0-9")
 
140
        self.br1.add_pending_merge(self.br2.revision_history()[6])
 
141
        commit(self.br1, "Commit fourtten", rev_id="a@u-0-6")
 
142
        self.br2.add_pending_merge(self.br1.revision_history()[6])
 
143
        commit(self.br2, "Commit fifteen", rev_id="b@u-0-10")
 
144
 
 
145
        from bzrlib.revision import MultipleRevisionSources
 
146
        self.sources = MultipleRevisionSources(self.br1, self.br2)
 
147
 
 
148
    def intervene(self, ancestor, revision, revision_history=None):
 
149
        from bzrlib.revision import get_intervening_revisions
 
150
        return get_intervening_revisions(ancestor,revision, self.sources, 
 
151
                                         revision_history)
 
152
 
 
153
    def test_intervene(self):
 
154
        """Find intermediate revisions, without requiring history"""
 
155
        from bzrlib.errors import NotAncestor, NoSuchRevision
 
156
        assert len(self.intervene('a@u-0-0', 'a@u-0-0')) == 0
 
157
        self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-1'), ['a@u-0-1'])
 
158
        self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-2'), 
 
159
                         ['a@u-0-1', 'a@u-0-2'])
 
160
        self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-3'), 
 
161
                         ['a@u-0-1', 'a@u-0-2', 'b@u-0-3'])
 
162
        self.assertEqual(self.intervene('b@u-0-3', 'a@u-0-3'), 
 
163
                         ['b@u-0-4', 'a@u-0-3'])
 
164
        self.assertEqual(self.intervene('a@u-0-2', 'a@u-0-3', 
 
165
                                        self.br1.revision_history()), 
 
166
                         ['a@u-0-3'])
 
167
        self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-5', 
 
168
                                        self.br1.revision_history()), 
 
169
                         ['a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4', 
 
170
                          'a@u-0-5'])
 
171
        self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-6', 
 
172
                         self.br1.revision_history()), 
 
173
                         ['a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4', 
 
174
                          'b@u-0-6'])
 
175
        self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-5'), 
 
176
                         ['a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4', 
 
177
                          'b@u-0-5'])
 
178
        self.assertEqual(self.intervene('b@u-0-3', 'b@u-0-6', 
 
179
                         self.br2.revision_history()), 
 
180
                         ['b@u-0-4', 'b@u-0-5', 'b@u-0-6'])
 
181
        self.assertEqual(self.intervene('b@u-0-6', 'b@u-0-10'), 
 
182
                         ['b@u-0-7', 'b@u-0-8', 'b@u-0-9', 'b@u-0-10'])
 
183
        self.assertEqual(self.intervene('b@u-0-6', 'b@u-0-10', 
 
184
                                        self.br2.revision_history()), 
 
185
                         ['b@u-0-7', 'b@u-0-8', 'b@u-0-9', 'b@u-0-10'])
 
186
        self.assertRaises(NotAncestor, self.intervene, 'b@u-0-10', 'b@u-0-6', 
 
187
                          self.br2.revision_history())
 
188
        self.assertRaises(NoSuchRevision, self.intervene, 'c@u-0-10', 
 
189
                          'b@u-0-6', self.br2.revision_history())
 
190
        self.assertRaises(NoSuchRevision, self.intervene, 'b@u-0-10', 
 
191
                          'c@u-0-6', self.br2.revision_history())
 
192
 
 
193
 
 
194
class TestCommonAncestor(TestCaseInTempDir):
189
195
    """Test checking whether a revision is an ancestor of another revision"""
190
196
 
 
197
    def test_old_common_ancestor(self):
 
198
        """Pick a resonable merge base using the old functionality"""
 
199
        from bzrlib.revision import find_present_ancestors
 
200
        from bzrlib.revision import old_common_ancestor as common_ancestor
 
201
        from bzrlib.revision import MultipleRevisionSources
 
202
        br1, br2 = make_branches()
 
203
        revisions = br1.revision_history()
 
204
        revisions_2 = br2.revision_history()
 
205
        sources = MultipleRevisionSources(br1, br2)
 
206
 
 
207
        expected_ancestors_list = {revisions[3]:(0, 0), 
 
208
                                   revisions[2]:(1, 1),
 
209
                                   revisions_2[4]:(2, 1), 
 
210
                                   revisions[1]:(3, 2),
 
211
                                   revisions_2[3]:(4, 2),
 
212
                                   revisions[0]:(5, 3) }
 
213
        ancestors_list = find_present_ancestors(revisions[3], sources)
 
214
        assert len(expected_ancestors_list) == len(ancestors_list)
 
215
        for key, value in expected_ancestors_list.iteritems():
 
216
            self.assertEqual(ancestors_list[key], value, 
 
217
                              "key %r, %r != %r" % (key, ancestors_list[key],
 
218
                                                    value))
 
219
 
 
220
        self.assertEqual(common_ancestor(revisions[0], revisions[0], sources),
 
221
                          revisions[0])
 
222
        self.assertEqual(common_ancestor(revisions[1], revisions[2], sources),
 
223
                          revisions[1])
 
224
        self.assertEqual(common_ancestor(revisions[1], revisions[1], sources),
 
225
                          revisions[1])
 
226
        self.assertEqual(common_ancestor(revisions[2], revisions_2[4], sources),
 
227
                          revisions[2])
 
228
        self.assertEqual(common_ancestor(revisions[3], revisions_2[4], sources),
 
229
                          revisions_2[4])
 
230
        self.assertEqual(common_ancestor(revisions[4], revisions_2[5], sources),
 
231
                          revisions_2[4])
 
232
        self.assertEqual(common_ancestor(revisions[5], revisions_2[6], sources),
 
233
                          revisions[4])
 
234
        self.assertEqual(common_ancestor(revisions_2[6], revisions[5], sources),
 
235
                          revisions_2[5])
 
236
 
191
237
    def test_common_ancestor(self):
192
238
        """Pick a reasonable merge base"""
193
 
        br1, br2 = make_branches(self)
 
239
        from bzrlib.revision import find_present_ancestors
 
240
        from bzrlib.revision import common_ancestor
 
241
        from bzrlib.revision import MultipleRevisionSources
 
242
        br1, br2 = make_branches()
194
243
        revisions = br1.revision_history()
195
244
        revisions_2 = br2.revision_history()
196
 
        sources = MultipleRevisionSources(br1.repository, br2.repository)
 
245
        sources = MultipleRevisionSources(br1, br2)
 
246
 
197
247
        expected_ancestors_list = {revisions[3]:(0, 0), 
198
248
                                   revisions[2]:(1, 1),
199
249
                                   revisions_2[4]:(2, 1), 
201
251
                                   revisions_2[3]:(4, 2),
202
252
                                   revisions[0]:(5, 3) }
203
253
        ancestors_list = find_present_ancestors(revisions[3], sources)
204
 
        self.assertEquals(len(expected_ancestors_list), len(ancestors_list))
 
254
        assert len(expected_ancestors_list) == len(ancestors_list)
205
255
        for key, value in expected_ancestors_list.iteritems():
206
256
            self.assertEqual(ancestors_list[key], value, 
207
257
                              "key %r, %r != %r" % (key, ancestors_list[key],
208
258
                                                    value))
 
259
 
209
260
        self.assertEqual(common_ancestor(revisions[0], revisions[0], sources),
210
261
                          revisions[0])
211
262
        self.assertEqual(common_ancestor(revisions[1], revisions[2], sources),
218
269
                          revisions_2[4])
219
270
        self.assertEqual(common_ancestor(revisions[4], revisions_2[5], sources),
220
271
                          revisions_2[4])
221
 
        self.assertTrue(common_ancestor(revisions[5], revisions_2[6], sources) in
222
 
                        (revisions[4], revisions_2[5]))
223
 
        self.assertTrue(common_ancestor(revisions_2[6], revisions[5], sources),
224
 
                        (revisions[4], revisions_2[5]))
225
 
        self.assertEqual(None, common_ancestor(None, revisions[5], sources))
226
 
 
227
 
    def test_combined(self):
228
 
        """combined_graph
229
 
        Ensure it's not order-sensitive
230
 
        """
231
 
        br1, br2 = make_branches(self)
232
 
        source = MultipleRevisionSources(br1.repository, br2.repository)
233
 
        combined_1 = combined_graph(br1.last_revision(), 
234
 
                                    br2.last_revision(), source)
235
 
        combined_2 = combined_graph(br2.last_revision(),
236
 
                                    br1.last_revision(), source)
237
 
        self.assertEquals(combined_1[1], combined_2[1])
238
 
        self.assertEquals(combined_1[2], combined_2[2])
239
 
        self.assertEquals(combined_1[3], combined_2[3])
240
 
        self.assertEquals(combined_1, combined_2)
241
 
 
242
 
    def test_get_history(self):
243
 
        # TODO: test ghosts on the left hand branch's impact
244
 
        # TODO: test ghosts on all parents, we should get some
245
 
        # indicator. i.e. NULL_REVISION
246
 
        # RBC 20060608
247
 
        tree = self.make_branch_and_tree('.')
248
 
        tree.commit('1', rev_id = '1', allow_pointless=True)
249
 
        tree.commit('2', rev_id = '2', allow_pointless=True)
250
 
        tree.commit('3', rev_id = '3', allow_pointless=True)
251
 
        rev = tree.branch.repository.get_revision('1')
252
 
        history = rev.get_history(tree.branch.repository)
253
 
        self.assertEqual([None, '1'], history)
254
 
        rev = tree.branch.repository.get_revision('2')
255
 
        history = rev.get_history(tree.branch.repository)
256
 
        self.assertEqual([None, '1', '2'], history)
257
 
        rev = tree.branch.repository.get_revision('3')
258
 
        history = rev.get_history(tree.branch.repository)
259
 
        self.assertEqual([None, '1', '2' ,'3'], history)
260
 
 
261
 
    def test_common_ancestor_rootless_graph(self):
262
 
        # common_ancestor on a graph with no reachable roots - only
263
 
        # ghosts - should still return a useful value.
264
 
        graph = Graph()
265
 
        # add a ghost node which would be a root if it wasn't a ghost.
266
 
        graph.add_ghost('a_ghost')
267
 
        # add a normal commit on top of that
268
 
        graph.add_node('rev1', ['a_ghost'])
269
 
        # add a left-branch revision
270
 
        graph.add_node('left', ['rev1'])
271
 
        # add a right-branch revision
272
 
        graph.add_node('right', ['rev1'])
273
 
        source = MockRevisionSource(graph)
274
 
        self.assertEqual('rev1', common_ancestor('left', 'right', source))
275
 
 
276
 
 
277
 
class TestMultipleRevisionSources(TestCaseWithTransport):
278
 
    """Tests for the MultipleRevisionSources adapter."""
279
 
 
280
 
    def test_get_revision_graph_merges_ghosts(self):
281
 
        # when we ask for the revision graph for B, which
282
 
        # is in repo 1 with a ghost of A, and which is not
283
 
        # in repo 2, which has A, the revision_graph()
284
 
        # should return A and B both.
285
 
        tree_1 = self.make_branch_and_tree('1')
286
 
        tree_1.add_pending_merge('A')
287
 
        tree_1.commit('foo', rev_id='B', allow_pointless=True)
288
 
        tree_2 = self.make_branch_and_tree('2')
289
 
        tree_2.commit('bar', rev_id='A', allow_pointless=True)
290
 
        source = MultipleRevisionSources(tree_1.branch.repository,
291
 
                                         tree_2.branch.repository)
292
 
        self.assertEqual({'B':['A'],
293
 
                          'A':[]},
294
 
                         source.get_revision_graph('B'))
 
272
        self.assertEqual(common_ancestor(revisions[5], revisions_2[6], sources),
 
273
                          revisions[4])
 
274
        self.assertEqual(common_ancestor(revisions_2[6], revisions[5], sources),
 
275
                          revisions[4])
 
276