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
17
from bzrlib.selftest import InTempDir
20
from bzrlib.selftest import TestCaseInTempDir
21
from bzrlib.branch import Branch
22
from bzrlib.commit import commit
23
from bzrlib.fetch import fetch
24
from bzrlib.revision import (find_present_ancestors, combined_graph,
25
is_ancestor, MultipleRevisionSources)
26
from bzrlib.trace import mutter
27
from bzrlib.errors import NoSuchRevision
20
29
def make_branches():
21
from bzrlib.branch import Branch
22
from bzrlib.commit import commit
24
30
os.mkdir("branch1")
25
br1 = Branch("branch1", init=True)
26
commit(br1, "Commit one")
27
commit(br1, "Commit two")
28
commit(br1, "Commit three")
31
br1 = Branch.initialize("branch1")
33
commit(br1, "Commit one", rev_id="a@u-0-0")
34
commit(br1, "Commit two", rev_id="a@u-0-1")
35
commit(br1, "Commit three", rev_id="a@u-0-2")
30
37
os.mkdir("branch2")
31
br2 = Branch("branch2", init=True)
38
br2 = Branch.initialize("branch2")
32
39
br2.update_revisions(br1)
33
commit(br2, "Commit four")
34
commit(br2, "Commit five")
40
commit(br2, "Commit four", rev_id="b@u-0-3")
41
commit(br2, "Commit five", rev_id="b@u-0-4")
35
42
revisions_2 = br2.revision_history()
44
fetch(from_branch=br2, to_branch=br1)
36
45
br1.add_pending_merge(revisions_2[4])
37
commit(br1, "Commit six")
46
assert revisions_2[4] == 'b@u-0-4'
47
commit(br1, "Commit six", rev_id="a@u-0-3")
48
commit(br1, "Commit seven", rev_id="a@u-0-4")
49
commit(br2, "Commit eight", rev_id="b@u-0-5")
51
fetch(from_branch=br2, to_branch=br1)
52
br1.add_pending_merge(br2.revision_history()[5])
53
commit(br1, "Commit nine", rev_id="a@u-0-5")
55
fetch(from_branch=br1, to_branch=br2)
56
br2.add_pending_merge(br1.revision_history()[4])
57
commit(br2, "Commit ten", rev_id="b@u-0-6")
59
fetch(from_branch=br2, to_branch=br1)
41
class TestIsAncestor(InTempDir):
42
"""Test checking whether a revision is an ancestor of another revision"""
44
from bzrlib.revision import is_ancestor, MultipleRevisionSources
45
from bzrlib.errors import NoSuchRevision
64
class TestIsAncestor(TestCaseInTempDir):
65
def test_recorded_ancestry(self):
66
"""Test that commit records all ancestors"""
67
br1, br2 = make_branches()
68
d = [('a@u-0-0', ['a@u-0-0']),
69
('a@u-0-1', ['a@u-0-0', 'a@u-0-1']),
70
('a@u-0-2', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2']),
71
('b@u-0-3', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3']),
72
('b@u-0-4', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3',
74
('a@u-0-3', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4',
76
('a@u-0-4', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4',
77
'a@u-0-3', 'a@u-0-4']),
78
('b@u-0-5', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4',
80
('a@u-0-5', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4',
82
'b@u-0-5', 'a@u-0-5']),
83
('b@u-0-6', ['a@u-0-0', 'a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4',
85
'b@u-0-5', 'b@u-0-6']),
87
for branch in br1, br2:
89
mutter('ancestry of {%s}: %r',
90
rev_id, branch.get_ancestry(rev_id))
91
self.assertEquals(sorted(branch.get_ancestry(rev_id)),
95
def test_is_ancestor(self):
96
"""Test checking whether a revision is an ancestor of another revision"""
46
97
br1, br2 = make_branches()
47
98
revisions = br1.revision_history()
48
99
revisions_2 = br2.revision_history()
49
sources = MultipleRevisionSources(br1, br2)
51
assert is_ancestor(revisions[0], revisions[0], sources)
102
assert is_ancestor(revisions[0], revisions[0], br1)
52
103
assert is_ancestor(revisions[1], revisions[0], sources)
53
104
assert not is_ancestor(revisions[0], revisions[1], sources)
54
105
assert is_ancestor(revisions_2[3], revisions[0], sources)
55
self.assertRaises(NoSuchRevision, is_ancestor, revisions_2[3],
106
# disabled mbp 20050914, doesn't seem to happen anymore
107
## self.assertRaises(NoSuchRevision, is_ancestor, revisions_2[3],
108
## revisions[0], br1)
57
109
assert is_ancestor(revisions[3], revisions_2[4], sources)
58
110
assert is_ancestor(revisions[3], revisions_2[4], br1)
59
111
assert is_ancestor(revisions[3], revisions_2[3], sources)
60
assert not is_ancestor(revisions[3], revisions_2[3], br1)
112
## assert not is_ancestor(revisions[3], revisions_2[3], br1)
116
class TestIntermediateRevisions(TestCaseInTempDir):
119
from bzrlib.commit import commit
120
TestCaseInTempDir.setUp(self)
121
self.br1, self.br2 = make_branches()
123
self.br2.commit("Commit eleven", rev_id="b@u-0-7")
124
self.br2.commit("Commit twelve", rev_id="b@u-0-8")
125
self.br2.commit("Commit thirtteen", rev_id="b@u-0-9")
127
fetch(from_branch=self.br2, to_branch=self.br1)
128
self.br1.add_pending_merge(self.br2.revision_history()[6])
129
self.br1.commit("Commit fourtten", rev_id="a@u-0-6")
131
fetch(from_branch=self.br1, to_branch=self.br2)
132
self.br2.add_pending_merge(self.br1.revision_history()[6])
133
self.br2.commit("Commit fifteen", rev_id="b@u-0-10")
135
from bzrlib.revision import MultipleRevisionSources
136
self.sources = MultipleRevisionSources(self.br1, self.br2)
138
def intervene(self, ancestor, revision, revision_history=None):
139
from bzrlib.revision import get_intervening_revisions
140
return get_intervening_revisions(ancestor,revision, self.sources,
143
def test_intervene(self):
144
"""Find intermediate revisions, without requiring history"""
145
from bzrlib.errors import NotAncestor, NoSuchRevision
146
assert len(self.intervene('a@u-0-0', 'a@u-0-0')) == 0
147
self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-1'), ['a@u-0-1'])
148
self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-2'),
149
['a@u-0-1', 'a@u-0-2'])
150
self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-3'),
151
['a@u-0-1', 'a@u-0-2', 'b@u-0-3'])
152
self.assertEqual(self.intervene('b@u-0-3', 'a@u-0-3'),
153
['b@u-0-4', 'a@u-0-3'])
154
self.assertEqual(self.intervene('a@u-0-2', 'a@u-0-3',
155
self.br1.revision_history()),
157
self.assertEqual(self.intervene('a@u-0-0', 'a@u-0-5',
158
self.br1.revision_history()),
159
['a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4',
161
self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-6',
162
self.br1.revision_history()),
163
['a@u-0-1', 'a@u-0-2', 'a@u-0-3', 'a@u-0-4',
165
self.assertEqual(self.intervene('a@u-0-0', 'b@u-0-5'),
166
['a@u-0-1', 'a@u-0-2', 'b@u-0-3', 'b@u-0-4',
168
self.assertEqual(self.intervene('b@u-0-3', 'b@u-0-6',
169
self.br2.revision_history()),
170
['b@u-0-4', 'b@u-0-5', 'b@u-0-6'])
171
self.assertEqual(self.intervene('b@u-0-6', 'b@u-0-10'),
172
['b@u-0-7', 'b@u-0-8', 'b@u-0-9', 'b@u-0-10'])
173
self.assertEqual(self.intervene('b@u-0-6', 'b@u-0-10',
174
self.br2.revision_history()),
175
['b@u-0-7', 'b@u-0-8', 'b@u-0-9', 'b@u-0-10'])
176
self.assertRaises(NotAncestor, self.intervene, 'b@u-0-10', 'b@u-0-6',
177
self.br2.revision_history())
178
self.assertRaises(NoSuchRevision, self.intervene, 'c@u-0-10',
179
'b@u-0-6', self.br2.revision_history())
180
self.assertRaises(NoSuchRevision, self.intervene, 'b@u-0-10',
181
'c@u-0-6', self.br2.revision_history())
184
class TestCommonAncestor(TestCaseInTempDir):
185
"""Test checking whether a revision is an ancestor of another revision"""
187
def test_old_common_ancestor(self):
188
"""Pick a resonable merge base using the old functionality"""
189
from bzrlib.revision import old_common_ancestor as common_ancestor
190
br1, br2 = make_branches()
191
revisions = br1.revision_history()
192
revisions_2 = br2.revision_history()
195
expected_ancestors_list = {revisions[3]:(0, 0),
197
revisions_2[4]:(2, 1),
199
revisions_2[3]:(4, 2),
200
revisions[0]:(5, 3) }
201
ancestors_list = find_present_ancestors(revisions[3], sources)
202
assert len(expected_ancestors_list) == len(ancestors_list)
203
for key, value in expected_ancestors_list.iteritems():
204
self.assertEqual(ancestors_list[key], value,
205
"key %r, %r != %r" % (key, ancestors_list[key],
208
self.assertEqual(common_ancestor(revisions[0], revisions[0], sources),
210
self.assertEqual(common_ancestor(revisions[1], revisions[2], sources),
212
self.assertEqual(common_ancestor(revisions[1], revisions[1], sources),
214
self.assertEqual(common_ancestor(revisions[2], revisions_2[4], sources),
216
self.assertEqual(common_ancestor(revisions[3], revisions_2[4], sources),
218
self.assertEqual(common_ancestor(revisions[4], revisions_2[5], sources),
220
self.assertEqual(common_ancestor(revisions[5], revisions_2[6], sources),
222
self.assertEqual(common_ancestor(revisions_2[6], revisions[5], sources),
225
def test_common_ancestor(self):
226
"""Pick a reasonable merge base"""
227
from bzrlib.revision import common_ancestor
228
br1, br2 = make_branches()
229
revisions = br1.revision_history()
230
revisions_2 = br2.revision_history()
231
sources = MultipleRevisionSources(br1, br2)
233
expected_ancestors_list = {revisions[3]:(0, 0),
235
revisions_2[4]:(2, 1),
237
revisions_2[3]:(4, 2),
238
revisions[0]:(5, 3) }
239
ancestors_list = find_present_ancestors(revisions[3], sources)
240
assert len(expected_ancestors_list) == len(ancestors_list)
241
for key, value in expected_ancestors_list.iteritems():
242
self.assertEqual(ancestors_list[key], value,
243
"key %r, %r != %r" % (key, ancestors_list[key],
246
self.assertEqual(common_ancestor(revisions[0], revisions[0], sources),
248
self.assertEqual(common_ancestor(revisions[1], revisions[2], sources),
250
self.assertEqual(common_ancestor(revisions[1], revisions[1], sources),
252
self.assertEqual(common_ancestor(revisions[2], revisions_2[4], sources),
254
self.assertEqual(common_ancestor(revisions[3], revisions_2[4], sources),
256
self.assertEqual(common_ancestor(revisions[4], revisions_2[5], sources),
258
self.assertEqual(common_ancestor(revisions[5], revisions_2[6], sources),
260
self.assertEqual(common_ancestor(revisions_2[6], revisions[5], sources),
263
def test_combined(self):
265
Ensure it's not order-sensitive
267
br1, br2 = make_branches()
268
source = MultipleRevisionSources(br1, br2)
269
combined_1 = combined_graph(br1.last_revision(),
270
br2.last_revision(), source)
271
combined_2 = combined_graph(br2.last_revision(),
272
br1.last_revision(), source)
273
assert combined_1[1] == combined_2[1]
274
assert combined_1[2] == combined_2[2]
275
assert combined_1[3] == combined_2[3]
276
assert combined_1 == combined_2