1
# Copyright (C) 2004, 2005 by Canonical Ltd
1
# Copyright (C) 2005-2010 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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
from bzrlib.builtins import merge
21
from bzrlib.branch import Branch
22
from bzrlib.tests import TestCaseWithTransport
23
from bzrlib.errors import NoCommonAncestor, NoCommits
24
from bzrlib.errors import NoSuchRevision
25
from bzrlib.revisionspec import RevisionSpec
28
class TestRevisionNamespaces(TestCaseWithTransport):
30
def test_revision_namespaces(self):
31
"""Test revision specifiers.
33
These identify revisions by date, etc."""
34
wt = self.make_branch_and_tree('.')
37
wt.commit('Commit one', rev_id='a@r-0-1', timestamp=time.time() - 60*60*24)
38
wt.commit('Commit two', rev_id='a@r-0-2')
39
wt.commit('Commit three', rev_id='a@r-0-3')
41
self.assertEquals(RevisionSpec(None).in_history(b), (0, None))
42
self.assertEquals(RevisionSpec(1).in_history(b), (1, 'a@r-0-1'))
43
self.assertEquals(RevisionSpec('revno:1').in_history(b),
45
self.assertEquals(RevisionSpec('revid:a@r-0-1').in_history(b),
47
self.assertRaises(NoSuchRevision,
48
RevisionSpec('revid:a@r-0-0').in_history, b)
49
self.assertRaises(TypeError, RevisionSpec, object)
51
self.assertEquals(RevisionSpec('date:today').in_history(b),
53
self.assertRaises(NoSuchRevision,
54
RevisionSpec('date:tomorrow').in_history, b)
55
self.assertEquals(RevisionSpec('date:yesterday').in_history(b),
57
self.assertEquals(RevisionSpec('before:date:today').in_history(b),
59
self.assertRaises(NoSuchRevision,
60
RevisionSpec('date:tomorrow').in_history, b)
62
self.assertEquals(RevisionSpec('last:1').in_history(b),
64
self.assertEquals(RevisionSpec('-1').in_history(b), (3, 'a@r-0-3'))
65
# self.assertEquals(b.get_revision_info('last:1'), (3, 'a@r-0-3'))
66
# self.assertEquals(b.get_revision_info('-1'), (3, 'a@r-0-3'))
68
self.assertEquals(RevisionSpec('ancestor:.').in_history(b).rev_id,
72
wt2 = self.make_branch_and_tree('newbranch')
74
self.assertRaises(NoCommits, RevisionSpec('ancestor:.').in_history, b2)
76
d3 = b.bzrdir.sprout('copy')
78
wt3 = d3.open_workingtree()
79
wt3.commit('Commit four', rev_id='b@r-0-4')
80
self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
82
merge(['copy', -1], [None, None])
83
wt.commit('Commit five', rev_id='a@r-0-4')
84
self.assertEquals(RevisionSpec('ancestor:copy').in_history(b).rev_id,
86
self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
89
# This should be in the revision store, but not in revision-history
90
self.assertEquals((None, 'b@r-0-4'),
91
RevisionSpec('revid:b@r-0-4').in_history(b))
93
def test_branch_namespace(self):
94
"""Ensure that the branch namespace pulls in the requisite content."""
95
self.build_tree(['branch1/', 'branch1/file', 'branch2/'])
96
wt = self.make_branch_and_tree('branch1')
100
d2 = branch.bzrdir.sprout('branch2')
101
print >> open('branch2/file', 'w'), 'new content'
102
branch2 = d2.open_branch()
103
d2.open_workingtree().commit('update file', rev_id='A')
104
spec = RevisionSpec('branch:./branch2/.bzr/../')
105
rev_info = spec.in_history(branch)
106
self.assertEqual(rev_info, (None, 'A'))
26
revision as _mod_revision,
28
from bzrlib.tests import TestCase, TestCaseWithTransport
29
from bzrlib.revisionspec import (
36
def spec_in_history(spec, branch):
37
"""A simple helper to change a revision spec into a branch search"""
38
return RevisionSpec.from_string(spec).in_history(branch)
41
# Basic class, which just creates a really basic set of revisions
42
class TestRevisionSpec(TestCaseWithTransport):
45
super(TestRevisionSpec, self).setUp()
46
# this sets up a revision graph:
51
self.tree = self.make_branch_and_tree('tree')
52
self.build_tree(['tree/a'])
53
self.tree.lock_write()
54
self.addCleanup(self.tree.unlock)
56
self.tree.commit('a', rev_id='r1')
58
self.tree2 = self.tree.bzrdir.sprout('tree2').open_workingtree()
59
self.tree2.commit('alt', rev_id='alt_r2')
61
self.tree.merge_from_branch(self.tree2.branch)
62
self.tree.commit('second', rev_id='r2')
64
def get_in_history(self, revision_spec):
65
return spec_in_history(revision_spec, self.tree.branch)
67
def assertInHistoryIs(self, exp_revno, exp_revision_id, revision_spec):
68
rev_info = self.get_in_history(revision_spec)
69
self.assertEqual(exp_revno, rev_info.revno,
70
'Revision spec: %r returned wrong revno: %r != %r'
71
% (revision_spec, exp_revno, rev_info.revno))
72
self.assertEqual(exp_revision_id, rev_info.rev_id,
73
'Revision spec: %r returned wrong revision id:'
75
% (revision_spec, exp_revision_id, rev_info.rev_id))
77
def assertInvalid(self, revision_spec, extra='',
78
invalid_as_revision_id=True):
80
self.get_in_history(revision_spec)
81
except errors.InvalidRevisionSpec, e:
82
self.assertEqual(revision_spec, e.spec)
83
self.assertEqual(extra, e.extra)
85
self.fail('Expected InvalidRevisionSpec to be raised for'
86
' %r.in_history' % (revision_spec,))
87
if invalid_as_revision_id:
89
spec = RevisionSpec.from_string(revision_spec)
90
spec.as_revision_id(self.tree.branch)
91
except errors.InvalidRevisionSpec, e:
92
self.assertEqual(revision_spec, e.spec)
93
self.assertEqual(extra, e.extra)
95
self.fail('Expected InvalidRevisionSpec to be raised for'
96
' %r.as_revision_id' % (revision_spec,))
98
def assertAsRevisionId(self, revision_id, revision_spec):
99
"""Calling as_revision_id() should return the specified id."""
100
spec = RevisionSpec.from_string(revision_spec)
101
self.assertEqual(revision_id,
102
spec.as_revision_id(self.tree.branch))
104
def get_as_tree(self, revision_spec, tree=None):
107
spec = RevisionSpec.from_string(revision_spec)
108
return spec.as_tree(tree.branch)
111
class RevisionSpecMatchOnTrap(RevisionSpec):
113
def _match_on(self, branch, revs):
114
self.last_call = (branch, revs)
115
return super(RevisionSpecMatchOnTrap, self)._match_on(branch, revs)
118
class TestRevisionSpecBase(TestRevisionSpec):
120
def test_wants_revision_history(self):
121
# If wants_revision_history = True, then _match_on should get the
122
# branch revision history
123
spec = RevisionSpecMatchOnTrap('foo', _internal=True)
124
spec.in_history(self.tree.branch)
126
self.assertEqual((self.tree.branch, ['r1' ,'r2']),
129
def test_wants_no_revision_history(self):
130
# If wants_revision_history = False, then _match_on should get None for
131
# the branch revision history
132
spec = RevisionSpecMatchOnTrap('foo', _internal=True)
133
spec.wants_revision_history = False
134
spec.in_history(self.tree.branch)
136
self.assertEqual((self.tree.branch, None), spec.last_call)
140
class TestOddRevisionSpec(TestRevisionSpec):
141
"""Test things that aren't normally thought of as revision specs"""
144
self.assertInHistoryIs(None, None, None)
146
def test_object(self):
147
self.assertRaises(TypeError, RevisionSpec.from_string, object())
150
class TestRevisionSpec_dwim(TestRevisionSpec):
152
# Don't need to test revno's explicitly since TRS_revno already
153
# covers that well for us
154
def test_dwim_spec_revno(self):
155
self.assertInHistoryIs(2, 'r2', '2')
156
self.assertAsRevisionId('alt_r2', '1.1.1')
158
def test_dwim_spec_revid(self):
159
self.assertInHistoryIs(2, 'r2', 'r2')
161
def test_dwim_spec_tag(self):
162
self.tree.branch.tags.set_tag('footag', 'r1')
163
self.assertAsRevisionId('r1', 'footag')
164
self.tree.branch.tags.delete_tag('footag')
165
self.assertRaises(errors.InvalidRevisionSpec,
166
self.get_in_history, 'footag')
168
def test_dwim_spec_tag_that_looks_like_revno(self):
169
# Test that we slip past revno with things that look like revnos,
170
# but aren't. Tags are convenient for testing this since we can
171
# make them look however we want.
172
self.tree.branch.tags.set_tag('3', 'r2')
173
self.assertAsRevisionId('r2', '3')
174
self.build_tree(['tree/b'])
176
self.tree.commit('b', rev_id='r3')
177
self.assertAsRevisionId('r3', '3')
179
def test_dwim_spec_date(self):
180
self.assertAsRevisionId('r1', 'today')
182
def test_dwim_spec_branch(self):
183
self.assertInHistoryIs(None, 'alt_r2', 'tree2')
185
def test_dwim_spec_nonexistent(self):
186
self.assertInvalid('somethingrandom', invalid_as_revision_id=False)
187
self.assertInvalid('-1.1', invalid_as_revision_id=False)
188
self.assertInvalid('.1', invalid_as_revision_id=False)
189
self.assertInvalid('1..1', invalid_as_revision_id=False)
190
self.assertInvalid('1.2..1', invalid_as_revision_id=False)
191
self.assertInvalid('1.', invalid_as_revision_id=False)
194
class TestRevisionSpec_revno(TestRevisionSpec):
196
def test_positive_int(self):
197
self.assertInHistoryIs(0, 'null:', '0')
198
self.assertInHistoryIs(1, 'r1', '1')
199
self.assertInHistoryIs(2, 'r2', '2')
200
self.assertInvalid('3')
202
def test_dotted_decimal(self):
203
self.assertInHistoryIs(None, 'alt_r2', '1.1.1')
204
self.assertInvalid('1.1.123')
206
def test_negative_int(self):
207
self.assertInHistoryIs(2, 'r2', '-1')
208
self.assertInHistoryIs(1, 'r1', '-2')
210
self.assertInHistoryIs(1, 'r1', '-3')
211
self.assertInHistoryIs(1, 'r1', '-4')
212
self.assertInHistoryIs(1, 'r1', '-100')
214
def test_positive(self):
215
self.assertInHistoryIs(0, 'null:', 'revno:0')
216
self.assertInHistoryIs(1, 'r1', 'revno:1')
217
self.assertInHistoryIs(2, 'r2', 'revno:2')
219
self.assertInvalid('revno:3')
221
def test_negative(self):
222
self.assertInHistoryIs(2, 'r2', 'revno:-1')
223
self.assertInHistoryIs(1, 'r1', 'revno:-2')
225
self.assertInHistoryIs(1, 'r1', 'revno:-3')
226
self.assertInHistoryIs(1, 'r1', 'revno:-4')
228
def test_invalid_number(self):
229
# Get the right exception text
232
except ValueError, e:
234
self.assertInvalid('revno:X', extra='\n' + str(e))
236
def test_missing_number_and_branch(self):
237
self.assertInvalid('revno::',
238
extra='\ncannot have an empty revno and no branch')
240
def test_invalid_number_with_branch(self):
243
except ValueError, e:
245
self.assertInvalid('revno:X:tree2', extra='\n' + str(e))
247
def test_non_exact_branch(self):
248
# It seems better to require an exact path to the branch
249
# Branch.open() rather than using Branch.open_containing()
250
spec = RevisionSpec.from_string('revno:2:tree2/a')
251
self.assertRaises(errors.NotBranchError,
252
spec.in_history, self.tree.branch)
254
def test_with_branch(self):
255
# Passing a URL overrides the supplied branch path
256
revinfo = self.get_in_history('revno:2:tree2')
257
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
258
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
259
self.assertEqual(2, revinfo.revno)
260
self.assertEqual('alt_r2', revinfo.rev_id)
262
def test_int_with_branch(self):
263
revinfo = self.get_in_history('2:tree2')
264
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
265
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
266
self.assertEqual(2, revinfo.revno)
267
self.assertEqual('alt_r2', revinfo.rev_id)
269
def test_with_url(self):
270
url = self.get_url() + '/tree2'
271
revinfo = self.get_in_history('revno:2:%s' % (url,))
272
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
273
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
274
self.assertEqual(2, revinfo.revno)
275
self.assertEqual('alt_r2', revinfo.rev_id)
277
def test_negative_with_url(self):
278
url = self.get_url() + '/tree2'
279
revinfo = self.get_in_history('revno:-1:%s' % (url,))
280
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
281
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
282
self.assertEqual(2, revinfo.revno)
283
self.assertEqual('alt_r2', revinfo.rev_id)
285
def test_different_history_lengths(self):
286
# Make sure we use the revisions and offsets in the supplied branch
287
# not the ones in the original branch.
288
self.tree2.commit('three', rev_id='r3')
289
self.assertInHistoryIs(3, 'r3', 'revno:3:tree2')
290
self.assertInHistoryIs(3, 'r3', 'revno:-1:tree2')
292
def test_invalid_branch(self):
293
self.assertRaises(errors.NotBranchError,
294
self.get_in_history, 'revno:-1:tree3')
296
def test_invalid_revno_in_branch(self):
297
self.tree.commit('three', rev_id='r3')
298
self.assertInvalid('revno:3:tree2')
300
def test_revno_n_path(self):
301
"""Old revno:N:path tests"""
302
wta = self.make_branch_and_tree('a')
305
wta.commit('Commit one', rev_id='a@r-0-1')
306
wta.commit('Commit two', rev_id='a@r-0-2')
307
wta.commit('Commit three', rev_id='a@r-0-3')
309
wtb = self.make_branch_and_tree('b')
312
wtb.commit('Commit one', rev_id='b@r-0-1')
313
wtb.commit('Commit two', rev_id='b@r-0-2')
314
wtb.commit('Commit three', rev_id='b@r-0-3')
317
self.assertEqual((1, 'a@r-0-1'),
318
spec_in_history('revno:1:a/', ba))
319
# The argument of in_history should be ignored since it is
320
# redundant with the path in the spec.
321
self.assertEqual((1, 'a@r-0-1'),
322
spec_in_history('revno:1:a/', None))
323
self.assertEqual((1, 'a@r-0-1'),
324
spec_in_history('revno:1:a/', bb))
325
self.assertEqual((2, 'b@r-0-2'),
326
spec_in_history('revno:2:b/', None))
328
def test_as_revision_id(self):
329
self.assertAsRevisionId('null:', '0')
330
self.assertAsRevisionId('r1', '1')
331
self.assertAsRevisionId('r2', '2')
332
self.assertAsRevisionId('r1', '-2')
333
self.assertAsRevisionId('r2', '-1')
334
self.assertAsRevisionId('alt_r2', '1.1.1')
336
def test_as_tree(self):
337
tree = self.get_as_tree('0')
338
self.assertEquals(_mod_revision.NULL_REVISION, tree.get_revision_id())
339
tree = self.get_as_tree('1')
340
self.assertEquals('r1', tree.get_revision_id())
341
tree = self.get_as_tree('2')
342
self.assertEquals('r2', tree.get_revision_id())
343
tree = self.get_as_tree('-2')
344
self.assertEquals('r1', tree.get_revision_id())
345
tree = self.get_as_tree('-1')
346
self.assertEquals('r2', tree.get_revision_id())
347
tree = self.get_as_tree('1.1.1')
348
self.assertEquals('alt_r2', tree.get_revision_id())
351
class TestRevisionSpec_revid(TestRevisionSpec):
353
def test_in_history(self):
354
# We should be able to access revisions that are directly
356
self.assertInHistoryIs(1, 'r1', 'revid:r1')
357
self.assertInHistoryIs(2, 'r2', 'revid:r2')
359
def test_missing(self):
360
self.assertInvalid('revid:r3', invalid_as_revision_id=False)
362
def test_merged(self):
363
"""We can reach revisions in the ancestry"""
364
self.assertInHistoryIs(None, 'alt_r2', 'revid:alt_r2')
366
def test_not_here(self):
367
self.tree2.commit('alt third', rev_id='alt_r3')
368
# It exists in tree2, but not in tree
369
self.assertInvalid('revid:alt_r3', invalid_as_revision_id=False)
371
def test_in_repository(self):
372
"""We can get any revision id in the repository"""
373
# XXX: This may change in the future, but for now, it is true
374
self.tree2.commit('alt third', rev_id='alt_r3')
375
self.tree.branch.repository.fetch(self.tree2.branch.repository,
376
revision_id='alt_r3')
377
self.assertInHistoryIs(None, 'alt_r3', 'revid:alt_r3')
379
def test_unicode(self):
380
"""We correctly convert a unicode ui string to an encoded revid."""
381
revision_id = u'\N{SNOWMAN}'.encode('utf-8')
382
self.tree.commit('unicode', rev_id=revision_id)
383
self.assertInHistoryIs(3, revision_id, u'revid:\N{SNOWMAN}')
384
self.assertInHistoryIs(3, revision_id, 'revid:' + revision_id)
386
def test_as_revision_id(self):
387
self.assertAsRevisionId('r1', 'revid:r1')
388
self.assertAsRevisionId('r2', 'revid:r2')
389
self.assertAsRevisionId('alt_r2', 'revid:alt_r2')
392
class TestRevisionSpec_last(TestRevisionSpec):
394
def test_positive(self):
395
self.assertInHistoryIs(2, 'r2', 'last:1')
396
self.assertInHistoryIs(1, 'r1', 'last:2')
397
self.assertInHistoryIs(0, 'null:', 'last:3')
399
def test_empty(self):
400
self.assertInHistoryIs(2, 'r2', 'last:')
402
def test_negative(self):
403
self.assertInvalid('last:-1',
404
extra='\nyou must supply a positive value')
406
def test_missing(self):
407
self.assertInvalid('last:4')
409
def test_no_history(self):
410
tree = self.make_branch_and_tree('tree3')
412
self.assertRaises(errors.NoCommits,
413
spec_in_history, 'last:', tree.branch)
415
def test_not_a_number(self):
418
except ValueError, e:
420
self.assertInvalid('last:Y', extra='\n' + str(e))
422
def test_as_revision_id(self):
423
self.assertAsRevisionId('r2', 'last:1')
424
self.assertAsRevisionId('r1', 'last:2')
427
class TestRevisionSpec_before(TestRevisionSpec):
430
self.assertInHistoryIs(1, 'r1', 'before:2')
431
self.assertInHistoryIs(1, 'r1', 'before:-1')
433
def test_before_one(self):
434
self.assertInHistoryIs(0, 'null:', 'before:1')
436
def test_before_none(self):
437
self.assertInvalid('before:0',
438
extra='\ncannot go before the null: revision')
440
def test_revid(self):
441
self.assertInHistoryIs(1, 'r1', 'before:revid:r2')
444
self.assertInHistoryIs(1, 'r1', 'before:last:1')
446
def test_alt_revid(self):
447
# This will grab the left-most ancestor for alternate histories
448
self.assertInHistoryIs(1, 'r1', 'before:revid:alt_r2')
450
def test_alt_no_parents(self):
451
new_tree = self.make_branch_and_tree('new_tree')
452
new_tree.commit('first', rev_id='new_r1')
453
self.tree.branch.repository.fetch(new_tree.branch.repository,
454
revision_id='new_r1')
455
self.assertInHistoryIs(0, 'null:', 'before:revid:new_r1')
457
def test_as_revision_id(self):
458
self.assertAsRevisionId('r1', 'before:revid:r2')
459
self.assertAsRevisionId('r1', 'before:2')
460
self.assertAsRevisionId('r1', 'before:1.1.1')
461
self.assertAsRevisionId('r1', 'before:revid:alt_r2')
464
class TestRevisionSpec_tag(TestRevisionSpec):
466
def make_branch_and_tree(self, relpath):
467
# override format as the default one may not support tags
468
return TestRevisionSpec.make_branch_and_tree(
469
self, relpath, format='dirstate-tags')
471
def test_from_string_tag(self):
472
spec = RevisionSpec.from_string('tag:bzr-0.14')
473
self.assertIsInstance(spec, RevisionSpec_tag)
474
self.assertEqual(spec.spec, 'bzr-0.14')
476
def test_lookup_tag(self):
477
self.tree.branch.tags.set_tag('bzr-0.14', 'r1')
478
self.assertInHistoryIs(1, 'r1', 'tag:bzr-0.14')
479
self.tree.branch.tags.set_tag('null_rev', 'null:')
480
self.assertInHistoryIs(0, 'null:', 'tag:null_rev')
482
def test_failed_lookup(self):
483
# tags that don't exist give a specific message: arguably we should
484
# just give InvalidRevisionSpec but I think this is more helpful
485
self.assertRaises(errors.NoSuchTag,
487
'tag:some-random-tag')
489
def test_as_revision_id(self):
490
self.tree.branch.tags.set_tag('my-tag', 'r2')
491
self.tree.branch.tags.set_tag('null_rev', 'null:')
492
self.assertAsRevisionId('r2', 'tag:my-tag')
493
self.assertAsRevisionId('null:', 'tag:null_rev')
494
self.assertAsRevisionId('r1', 'before:tag:my-tag')
497
class TestRevisionSpec_date(TestRevisionSpec):
500
super(TestRevisionSpec, self).setUp()
502
new_tree = self.make_branch_and_tree('new_tree')
503
new_tree.commit('Commit one', rev_id='new_r1',
504
timestamp=time.time() - 60*60*24)
505
new_tree.commit('Commit two', rev_id='new_r2')
506
new_tree.commit('Commit three', rev_id='new_r3')
510
def test_tomorrow(self):
511
self.assertInvalid('date:tomorrow')
513
def test_today(self):
514
self.assertInHistoryIs(2, 'new_r2', 'date:today')
515
self.assertInHistoryIs(1, 'new_r1', 'before:date:today')
517
def test_yesterday(self):
518
self.assertInHistoryIs(1, 'new_r1', 'date:yesterday')
520
def test_invalid(self):
521
self.assertInvalid('date:foobar', extra='\ninvalid date')
522
# You must have '-' between year/month/day
523
self.assertInvalid('date:20040404', extra='\ninvalid date')
524
# Need 2 digits for each date piece
525
self.assertInvalid('date:2004-4-4', extra='\ninvalid date')
528
now = datetime.datetime.now()
529
self.assertInHistoryIs(2, 'new_r2',
530
'date:%04d-%02d-%02d' % (now.year, now.month, now.day))
532
def test_as_revision_id(self):
533
self.assertAsRevisionId('new_r2', 'date:today')
536
class TestRevisionSpec_ancestor(TestRevisionSpec):
538
def test_non_exact_branch(self):
539
# It seems better to require an exact path to the branch
540
# Branch.open() rather than using Branch.open_containing()
541
self.assertRaises(errors.NotBranchError,
542
self.get_in_history, 'ancestor:tree2/a')
544
def test_simple(self):
545
# Common ancestor of trees is 'alt_r2'
546
self.assertInHistoryIs(None, 'alt_r2', 'ancestor:tree2')
548
# Going the other way, we get a valid revno
550
self.tree = self.tree2
552
self.assertInHistoryIs(2, 'alt_r2', 'ancestor:tree')
555
self.assertInHistoryIs(2, 'r2', 'ancestor:tree')
557
def test_unrelated(self):
558
new_tree = self.make_branch_and_tree('new_tree')
560
new_tree.commit('Commit one', rev_id='new_r1')
561
new_tree.commit('Commit two', rev_id='new_r2')
562
new_tree.commit('Commit three', rev_id='new_r3')
564
# With no common ancestor, we should raise another user error
565
self.assertRaises(errors.NoCommonAncestor,
566
self.get_in_history, 'ancestor:new_tree')
568
def test_no_commits(self):
569
new_tree = self.make_branch_and_tree('new_tree')
570
self.assertRaises(errors.NoCommits,
571
spec_in_history, 'ancestor:new_tree',
574
self.assertRaises(errors.NoCommits,
575
spec_in_history, 'ancestor:tree',
578
def test_as_revision_id(self):
579
self.assertAsRevisionId('alt_r2', 'ancestor:tree2')
581
def test_default(self):
582
# We don't have a parent to default to
583
self.assertRaises(errors.NotBranchError, self.get_in_history,
586
# Create a branch with a parent to default to
587
tree3 = self.tree.bzrdir.sprout('tree3').open_workingtree()
588
tree3.commit('foo', rev_id='r3')
590
self.assertInHistoryIs(2, 'r2', 'ancestor:')
593
class TestRevisionSpec_branch(TestRevisionSpec):
595
def test_non_exact_branch(self):
596
# It seems better to require an exact path to the branch
597
# Branch.open() rather than using Branch.open_containing()
598
self.assertRaises(errors.NotBranchError,
599
self.get_in_history, 'branch:tree2/a')
601
def test_simple(self):
602
self.assertInHistoryIs(None, 'alt_r2', 'branch:tree2')
605
self.assertInHistoryIs(2, 'r2', 'branch:tree')
607
def test_unrelated(self):
608
new_tree = self.make_branch_and_tree('new_tree')
610
new_tree.commit('Commit one', rev_id='new_r1')
611
new_tree.commit('Commit two', rev_id='new_r2')
612
new_tree.commit('Commit three', rev_id='new_r3')
614
self.assertInHistoryIs(None, 'new_r3', 'branch:new_tree')
616
# XXX: Right now, we use fetch() to make sure the remote revisions
617
# have been pulled into the local branch. We may change that
618
# behavior in the future.
619
self.failUnless(self.tree.branch.repository.has_revision('new_r3'))
621
def test_no_commits(self):
622
new_tree = self.make_branch_and_tree('new_tree')
623
self.assertRaises(errors.NoCommits,
624
self.get_in_history, 'branch:new_tree')
625
self.assertRaises(errors.NoCommits,
626
self.get_as_tree, 'branch:new_tree')
628
def test_as_revision_id(self):
629
self.assertAsRevisionId('alt_r2', 'branch:tree2')
631
def test_as_tree(self):
632
tree = self.get_as_tree('branch:tree', self.tree2)
633
self.assertEquals('r2', tree.get_revision_id())
634
self.assertFalse(self.tree2.branch.repository.has_revision('r2'))
637
class TestRevisionSpec_submit(TestRevisionSpec):
639
def test_submit_branch(self):
640
# Common ancestor of trees is 'alt_r2'
641
self.assertRaises(errors.NoSubmitBranch, self.get_in_history,
643
self.tree.branch.set_parent('../tree2')
644
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
645
self.tree.branch.set_parent('bogus')
646
self.assertRaises(errors.NotBranchError, self.get_in_history,
648
# submit branch overrides parent branch
649
self.tree.branch.set_submit_branch('tree2')
650
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
652
def test_as_revision_id(self):
653
self.tree.branch.set_submit_branch('tree2')
654
self.assertAsRevisionId('alt_r2', 'branch:tree2')