1
# Copyright (C) 2004, 2005 by Canonical Ltd
1
# Copyright (C) 2004, 2005, 2006, 2007 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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
from bzrlib.branch import Branch
21
from bzrlib.tests import TestCaseInTempDir
22
from bzrlib.errors import NoCommonAncestor, NoCommits
23
from bzrlib.errors import NoSuchRevision
24
from bzrlib.merge import merge
25
from bzrlib.revisionspec import RevisionSpec
27
class TestRevisionNamespaces(TestCaseInTempDir):
29
def test_revision_namespaces(self):
30
"""Test revision specifiers.
32
These identify revisions by date, etc."""
34
b = Branch.initialize(u'.')
36
b.working_tree().commit('Commit one', rev_id='a@r-0-1', timestamp=time.time() - 60*60*24)
37
b.working_tree().commit('Commit two', rev_id='a@r-0-2')
38
b.working_tree().commit('Commit three', rev_id='a@r-0-3')
40
self.assertEquals(RevisionSpec(None).in_history(b), (0, None))
41
self.assertEquals(RevisionSpec(1).in_history(b), (1, 'a@r-0-1'))
42
self.assertEquals(RevisionSpec('revno:1').in_history(b),
44
self.assertEquals(RevisionSpec('revid:a@r-0-1').in_history(b),
46
self.assertRaises(NoSuchRevision,
47
RevisionSpec('revid:a@r-0-0').in_history, b)
48
self.assertRaises(TypeError, RevisionSpec, object)
50
self.assertEquals(RevisionSpec('date:today').in_history(b),
52
self.assertEquals(RevisionSpec('date:yesterday').in_history(b),
54
self.assertEquals(RevisionSpec('before:date:today').in_history(b),
57
self.assertEquals(RevisionSpec('last:1').in_history(b),
59
self.assertEquals(RevisionSpec('-1').in_history(b), (3, 'a@r-0-3'))
60
# self.assertEquals(b.get_revision_info('last:1'), (3, 'a@r-0-3'))
61
# self.assertEquals(b.get_revision_info('-1'), (3, 'a@r-0-3'))
63
self.assertEquals(RevisionSpec('ancestor:.').in_history(b).rev_id,
67
b2 = Branch.initialize('newbranch')
68
self.assertRaises(NoCommits, RevisionSpec('ancestor:.').in_history, b2)
72
b3.working_tree().commit('Commit four', rev_id='b@r-0-4')
73
self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
75
merge(['copy', -1], [None, None])
76
b.working_tree().commit('Commit five', rev_id='a@r-0-4')
77
self.assertEquals(RevisionSpec('ancestor:copy').in_history(b).rev_id,
79
self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
82
# This should be in the revision store, but not in revision-history
83
self.assertEquals((None, 'b@r-0-4'),
84
RevisionSpec('revid:b@r-0-4').in_history(b))
86
def test_branch_namespace(self):
87
"""Ensure that the branch namespace pulls in the requisite content."""
88
self.build_tree(['branch1/', 'branch1/file', 'branch2/'])
89
branch = Branch.initialize('branch1')
90
branch.working_tree().add(['file'])
91
branch.working_tree().commit('add file')
92
branch.clone('branch2')
93
print >> open('branch2/file', 'w'), 'new content'
94
branch2 = Branch.open('branch2')
95
branch2.working_tree().commit('update file', rev_id='A')
96
spec = RevisionSpec('branch:./branch2/.bzr/../')
97
rev_info = spec.in_history(branch)
98
self.assertEqual(rev_info, (None, 'A'))
27
from bzrlib.tests import TestCase, TestCaseWithTransport
28
from bzrlib.revisionspec import (
35
def spec_in_history(spec, branch):
36
"""A simple helper to change a revision spec into a branch search"""
37
return RevisionSpec.from_string(spec).in_history(branch)
40
# Basic class, which just creates a really basic set of revisions
41
class TestRevisionSpec(TestCaseWithTransport):
44
super(TestRevisionSpec, self).setUp()
45
# this sets up a revision graph:
50
self.tree = self.make_branch_and_tree('tree')
51
self.build_tree(['tree/a'])
52
self.tree.lock_write()
53
self.addCleanup(self.tree.unlock)
55
self.tree.commit('a', rev_id='r1')
57
self.tree2 = self.tree.bzrdir.sprout('tree2').open_workingtree()
58
self.tree2.commit('alt', rev_id='alt_r2')
60
self.tree.merge_from_branch(self.tree2.branch)
61
self.tree.commit('second', rev_id='r2')
63
def get_in_history(self, revision_spec):
64
return spec_in_history(revision_spec, self.tree.branch)
66
def assertInHistoryIs(self, exp_revno, exp_revision_id, revision_spec):
67
rev_info = self.get_in_history(revision_spec)
68
self.assertEqual(exp_revno, rev_info.revno,
69
'Revision spec: %r returned wrong revno: %r != %r'
70
% (revision_spec, exp_revno, rev_info.revno))
71
self.assertEqual(exp_revision_id, rev_info.rev_id,
72
'Revision spec: %r returned wrong revision id:'
74
% (revision_spec, exp_revision_id, rev_info.rev_id))
76
def assertInvalid(self, revision_spec, extra='',
77
invalid_as_revision_id=True):
79
self.get_in_history(revision_spec)
80
except errors.InvalidRevisionSpec, e:
81
self.assertEqual(revision_spec, e.spec)
82
self.assertEqual(extra, e.extra)
84
self.fail('Expected InvalidRevisionSpec to be raised for'
85
' %r.in_history' % (revision_spec,))
86
if invalid_as_revision_id:
88
spec = RevisionSpec.from_string(revision_spec)
89
spec.as_revision_id(self.tree.branch)
90
except errors.InvalidRevisionSpec, e:
91
self.assertEqual(revision_spec, e.spec)
92
self.assertEqual(extra, e.extra)
94
self.fail('Expected InvalidRevisionSpec to be raised for'
95
' %r.as_revision_id' % (revision_spec,))
97
def assertAsRevisionId(self, revision_id, revision_spec):
98
"""Calling as_revision_id() should return the specified id."""
99
spec = RevisionSpec.from_string(revision_spec)
100
self.assertEqual(revision_id,
101
spec.as_revision_id(self.tree.branch))
104
class RevisionSpecMatchOnTrap(RevisionSpec):
106
def _match_on(self, branch, revs):
107
self.last_call = (branch, revs)
108
return super(RevisionSpecMatchOnTrap, self)._match_on(branch, revs)
111
class TestRevisionSpecBase(TestRevisionSpec):
113
def test_wants_revision_history(self):
114
# If wants_revision_history = True, then _match_on should get the
115
# branch revision history
116
spec = RevisionSpecMatchOnTrap('foo', _internal=True)
117
spec.in_history(self.tree.branch)
119
self.assertEqual((self.tree.branch, ['r1' ,'r2']),
122
def test_wants_no_revision_history(self):
123
# If wants_revision_history = False, then _match_on should get None for
124
# the branch revision history
125
spec = RevisionSpecMatchOnTrap('foo', _internal=True)
126
spec.wants_revision_history = False
127
spec.in_history(self.tree.branch)
129
self.assertEqual((self.tree.branch, None), spec.last_call)
133
class TestOddRevisionSpec(TestRevisionSpec):
134
"""Test things that aren't normally thought of as revision specs"""
137
self.assertInHistoryIs(None, None, None)
139
def test_object(self):
140
self.assertRaises(TypeError, RevisionSpec.from_string, object())
142
def test_unregistered_spec(self):
143
self.assertRaises(errors.NoSuchRevisionSpec,
144
RevisionSpec.from_string, 'foo')
145
self.assertRaises(errors.NoSuchRevisionSpec,
146
RevisionSpec.from_string, '123a')
150
class TestRevnoFromString(TestCase):
152
def test_from_string_dotted_decimal(self):
153
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '-1.1')
154
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '.1')
155
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1..1')
156
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1.2..1')
157
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1.')
158
self.assertIsInstance(RevisionSpec.from_string('1.1'), RevisionSpec_revno)
159
self.assertIsInstance(RevisionSpec.from_string('1.1.3'), RevisionSpec_revno)
162
class TestRevisionSpec_revno(TestRevisionSpec):
164
def test_positive_int(self):
165
self.assertInHistoryIs(0, 'null:', '0')
166
self.assertInHistoryIs(1, 'r1', '1')
167
self.assertInHistoryIs(2, 'r2', '2')
168
self.assertInvalid('3')
170
def test_dotted_decimal(self):
171
self.assertInHistoryIs(None, 'alt_r2', '1.1.1')
173
def test_negative_int(self):
174
self.assertInHistoryIs(2, 'r2', '-1')
175
self.assertInHistoryIs(1, 'r1', '-2')
177
self.assertInHistoryIs(1, 'r1', '-3')
178
self.assertInHistoryIs(1, 'r1', '-4')
179
self.assertInHistoryIs(1, 'r1', '-100')
181
def test_positive(self):
182
self.assertInHistoryIs(0, 'null:', 'revno:0')
183
self.assertInHistoryIs(1, 'r1', 'revno:1')
184
self.assertInHistoryIs(2, 'r2', 'revno:2')
186
self.assertInvalid('revno:3')
188
def test_negative(self):
189
self.assertInHistoryIs(2, 'r2', 'revno:-1')
190
self.assertInHistoryIs(1, 'r1', 'revno:-2')
192
self.assertInHistoryIs(1, 'r1', 'revno:-3')
193
self.assertInHistoryIs(1, 'r1', 'revno:-4')
195
def test_invalid_number(self):
196
# Get the right exception text
199
except ValueError, e:
201
self.assertInvalid('revno:X', extra='\n' + str(e))
203
def test_missing_number_and_branch(self):
204
self.assertInvalid('revno::',
205
extra='\ncannot have an empty revno and no branch')
207
def test_invalid_number_with_branch(self):
210
except ValueError, e:
212
self.assertInvalid('revno:X:tree2', extra='\n' + str(e))
214
def test_non_exact_branch(self):
215
# It seems better to require an exact path to the branch
216
# Branch.open() rather than using Branch.open_containing()
217
spec = RevisionSpec.from_string('revno:2:tree2/a')
218
self.assertRaises(errors.NotBranchError,
219
spec.in_history, self.tree.branch)
221
def test_with_branch(self):
222
# Passing a URL overrides the supplied branch path
223
revinfo = self.get_in_history('revno:2:tree2')
224
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
225
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
226
self.assertEqual(2, revinfo.revno)
227
self.assertEqual('alt_r2', revinfo.rev_id)
229
def test_int_with_branch(self):
230
revinfo = self.get_in_history('2:tree2')
231
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
232
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
233
self.assertEqual(2, revinfo.revno)
234
self.assertEqual('alt_r2', revinfo.rev_id)
236
def test_with_url(self):
237
url = self.get_url() + '/tree2'
238
revinfo = self.get_in_history('revno:2:%s' % (url,))
239
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
240
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
241
self.assertEqual(2, revinfo.revno)
242
self.assertEqual('alt_r2', revinfo.rev_id)
244
def test_negative_with_url(self):
245
url = self.get_url() + '/tree2'
246
revinfo = self.get_in_history('revno:-1:%s' % (url,))
247
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
248
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
249
self.assertEqual(2, revinfo.revno)
250
self.assertEqual('alt_r2', revinfo.rev_id)
252
def test_different_history_lengths(self):
253
# Make sure we use the revisions and offsets in the supplied branch
254
# not the ones in the original branch.
255
self.tree2.commit('three', rev_id='r3')
256
self.assertInHistoryIs(3, 'r3', 'revno:3:tree2')
257
self.assertInHistoryIs(3, 'r3', 'revno:-1:tree2')
259
def test_invalid_branch(self):
260
self.assertRaises(errors.NotBranchError,
261
self.get_in_history, 'revno:-1:tree3')
263
def test_invalid_revno_in_branch(self):
264
self.tree.commit('three', rev_id='r3')
265
self.assertInvalid('revno:3:tree2')
267
def test_revno_n_path(self):
268
"""Old revno:N:path tests"""
269
wta = self.make_branch_and_tree('a')
272
wta.commit('Commit one', rev_id='a@r-0-1')
273
wta.commit('Commit two', rev_id='a@r-0-2')
274
wta.commit('Commit three', rev_id='a@r-0-3')
276
wtb = self.make_branch_and_tree('b')
279
wtb.commit('Commit one', rev_id='b@r-0-1')
280
wtb.commit('Commit two', rev_id='b@r-0-2')
281
wtb.commit('Commit three', rev_id='b@r-0-3')
284
self.assertEqual((1, 'a@r-0-1'),
285
spec_in_history('revno:1:a/', ba))
286
# The argument of in_history should be ignored since it is
287
# redundant with the path in the spec.
288
self.assertEqual((1, 'a@r-0-1'),
289
spec_in_history('revno:1:a/', None))
290
self.assertEqual((1, 'a@r-0-1'),
291
spec_in_history('revno:1:a/', bb))
292
self.assertEqual((2, 'b@r-0-2'),
293
spec_in_history('revno:2:b/', None))
295
def test_as_revision_id(self):
296
self.assertAsRevisionId('null:', '0')
297
self.assertAsRevisionId('r1', '1')
298
self.assertAsRevisionId('r2', '2')
299
self.assertAsRevisionId('r1', '-2')
300
self.assertAsRevisionId('r2', '-1')
301
self.assertAsRevisionId('alt_r2', '1.1.1')
304
class TestRevisionSpec_revid(TestRevisionSpec):
306
def test_in_history(self):
307
# We should be able to access revisions that are directly
309
self.assertInHistoryIs(1, 'r1', 'revid:r1')
310
self.assertInHistoryIs(2, 'r2', 'revid:r2')
312
def test_missing(self):
313
self.assertInvalid('revid:r3', invalid_as_revision_id=False)
315
def test_merged(self):
316
"""We can reach revisions in the ancestry"""
317
self.assertInHistoryIs(None, 'alt_r2', 'revid:alt_r2')
319
def test_not_here(self):
320
self.tree2.commit('alt third', rev_id='alt_r3')
321
# It exists in tree2, but not in tree
322
self.assertInvalid('revid:alt_r3', invalid_as_revision_id=False)
324
def test_in_repository(self):
325
"""We can get any revision id in the repository"""
326
# XXX: This may change in the future, but for now, it is true
327
self.tree2.commit('alt third', rev_id='alt_r3')
328
self.tree.branch.repository.fetch(self.tree2.branch.repository,
329
revision_id='alt_r3')
330
self.assertInHistoryIs(None, 'alt_r3', 'revid:alt_r3')
332
def test_unicode(self):
333
"""We correctly convert a unicode ui string to an encoded revid."""
334
revision_id = u'\N{SNOWMAN}'.encode('utf-8')
335
self.tree.commit('unicode', rev_id=revision_id)
336
self.assertInHistoryIs(3, revision_id, u'revid:\N{SNOWMAN}')
337
self.assertInHistoryIs(3, revision_id, 'revid:' + revision_id)
339
def test_as_revision_id(self):
340
self.assertAsRevisionId('r1', 'revid:r1')
341
self.assertAsRevisionId('r2', 'revid:r2')
342
self.assertAsRevisionId('alt_r2', 'revid:alt_r2')
345
class TestRevisionSpec_last(TestRevisionSpec):
347
def test_positive(self):
348
self.assertInHistoryIs(2, 'r2', 'last:1')
349
self.assertInHistoryIs(1, 'r1', 'last:2')
350
self.assertInHistoryIs(0, 'null:', 'last:3')
352
def test_empty(self):
353
self.assertInHistoryIs(2, 'r2', 'last:')
355
def test_negative(self):
356
self.assertInvalid('last:-1',
357
extra='\nyou must supply a positive value')
359
def test_missing(self):
360
self.assertInvalid('last:4')
362
def test_no_history(self):
363
tree = self.make_branch_and_tree('tree3')
365
self.assertRaises(errors.NoCommits,
366
spec_in_history, 'last:', tree.branch)
368
def test_not_a_number(self):
371
except ValueError, e:
373
self.assertInvalid('last:Y', extra='\n' + str(e))
375
def test_as_revision_id(self):
376
self.assertAsRevisionId('r2', 'last:1')
377
self.assertAsRevisionId('r1', 'last:2')
380
class TestRevisionSpec_before(TestRevisionSpec):
383
self.assertInHistoryIs(1, 'r1', 'before:2')
384
self.assertInHistoryIs(1, 'r1', 'before:-1')
386
def test_before_one(self):
387
self.assertInHistoryIs(0, 'null:', 'before:1')
389
def test_before_none(self):
390
self.assertInvalid('before:0',
391
extra='\ncannot go before the null: revision')
393
def test_revid(self):
394
self.assertInHistoryIs(1, 'r1', 'before:revid:r2')
397
self.assertInHistoryIs(1, 'r1', 'before:last:1')
399
def test_alt_revid(self):
400
# This will grab the left-most ancestor for alternate histories
401
self.assertInHistoryIs(1, 'r1', 'before:revid:alt_r2')
403
def test_alt_no_parents(self):
404
new_tree = self.make_branch_and_tree('new_tree')
405
new_tree.commit('first', rev_id='new_r1')
406
self.tree.branch.repository.fetch(new_tree.branch.repository,
407
revision_id='new_r1')
408
self.assertInHistoryIs(0, 'null:', 'before:revid:new_r1')
410
def test_as_revision_id(self):
411
self.assertAsRevisionId('r1', 'before:revid:r2')
412
self.assertAsRevisionId('r1', 'before:2')
413
self.assertAsRevisionId('r1', 'before:1.1.1')
414
self.assertAsRevisionId('r1', 'before:revid:alt_r2')
417
class TestRevisionSpec_tag(TestRevisionSpec):
419
def make_branch_and_tree(self, relpath):
420
# override format as the default one may not support tags
421
return TestRevisionSpec.make_branch_and_tree(
422
self, relpath, format='dirstate-tags')
424
def test_from_string_tag(self):
425
spec = RevisionSpec.from_string('tag:bzr-0.14')
426
self.assertIsInstance(spec, RevisionSpec_tag)
427
self.assertEqual(spec.spec, 'bzr-0.14')
429
def test_lookup_tag(self):
430
self.tree.branch.tags.set_tag('bzr-0.14', 'r1')
431
self.assertInHistoryIs(1, 'r1', 'tag:bzr-0.14')
432
self.tree.branch.tags.set_tag('null_rev', 'null:')
433
self.assertInHistoryIs(0, 'null:', 'tag:null_rev')
435
def test_failed_lookup(self):
436
# tags that don't exist give a specific message: arguably we should
437
# just give InvalidRevisionSpec but I think this is more helpful
438
self.assertRaises(errors.NoSuchTag,
440
'tag:some-random-tag')
442
def test_as_revision_id(self):
443
self.tree.branch.tags.set_tag('my-tag', 'r2')
444
self.tree.branch.tags.set_tag('null_rev', 'null:')
445
self.assertAsRevisionId('r2', 'tag:my-tag')
446
self.assertAsRevisionId('null:', 'tag:null_rev')
447
self.assertAsRevisionId('r1', 'before:tag:my-tag')
450
class TestRevisionSpec_date(TestRevisionSpec):
453
super(TestRevisionSpec, self).setUp()
455
new_tree = self.make_branch_and_tree('new_tree')
456
new_tree.commit('Commit one', rev_id='new_r1',
457
timestamp=time.time() - 60*60*24)
458
new_tree.commit('Commit two', rev_id='new_r2')
459
new_tree.commit('Commit three', rev_id='new_r3')
463
def test_tomorrow(self):
464
self.assertInvalid('date:tomorrow')
466
def test_today(self):
467
self.assertInHistoryIs(2, 'new_r2', 'date:today')
468
self.assertInHistoryIs(1, 'new_r1', 'before:date:today')
470
def test_yesterday(self):
471
self.assertInHistoryIs(1, 'new_r1', 'date:yesterday')
473
def test_invalid(self):
474
self.assertInvalid('date:foobar', extra='\ninvalid date')
475
# You must have '-' between year/month/day
476
self.assertInvalid('date:20040404', extra='\ninvalid date')
477
# Need 2 digits for each date piece
478
self.assertInvalid('date:2004-4-4', extra='\ninvalid date')
481
now = datetime.datetime.now()
482
self.assertInHistoryIs(2, 'new_r2',
483
'date:%04d-%02d-%02d' % (now.year, now.month, now.day))
485
def test_as_revision_id(self):
486
self.assertAsRevisionId('new_r2', 'date:today')
489
class TestRevisionSpec_ancestor(TestRevisionSpec):
491
def test_non_exact_branch(self):
492
# It seems better to require an exact path to the branch
493
# Branch.open() rather than using Branch.open_containing()
494
self.assertRaises(errors.NotBranchError,
495
self.get_in_history, 'ancestor:tree2/a')
497
def test_simple(self):
498
# Common ancestor of trees is 'alt_r2'
499
self.assertInHistoryIs(None, 'alt_r2', 'ancestor:tree2')
501
# Going the other way, we get a valid revno
503
self.tree = self.tree2
505
self.assertInHistoryIs(2, 'alt_r2', 'ancestor:tree')
508
self.assertInHistoryIs(2, 'r2', 'ancestor:tree')
510
def test_unrelated(self):
511
new_tree = self.make_branch_and_tree('new_tree')
513
new_tree.commit('Commit one', rev_id='new_r1')
514
new_tree.commit('Commit two', rev_id='new_r2')
515
new_tree.commit('Commit three', rev_id='new_r3')
517
# With no common ancestor, we should raise another user error
518
self.assertRaises(errors.NoCommonAncestor,
519
self.get_in_history, 'ancestor:new_tree')
521
def test_no_commits(self):
522
new_tree = self.make_branch_and_tree('new_tree')
523
self.assertRaises(errors.NoCommits,
524
spec_in_history, 'ancestor:new_tree',
527
self.assertRaises(errors.NoCommits,
528
spec_in_history, 'ancestor:tree',
531
def test_as_revision_id(self):
532
self.assertAsRevisionId('alt_r2', 'ancestor:tree2')
535
class TestRevisionSpec_branch(TestRevisionSpec):
537
def test_non_exact_branch(self):
538
# It seems better to require an exact path to the branch
539
# Branch.open() rather than using Branch.open_containing()
540
self.assertRaises(errors.NotBranchError,
541
self.get_in_history, 'branch:tree2/a')
543
def test_simple(self):
544
self.assertInHistoryIs(None, 'alt_r2', 'branch:tree2')
547
self.assertInHistoryIs(2, 'r2', 'branch:tree')
549
def test_unrelated(self):
550
new_tree = self.make_branch_and_tree('new_tree')
552
new_tree.commit('Commit one', rev_id='new_r1')
553
new_tree.commit('Commit two', rev_id='new_r2')
554
new_tree.commit('Commit three', rev_id='new_r3')
556
self.assertInHistoryIs(None, 'new_r3', 'branch:new_tree')
558
# XXX: Right now, we use fetch() to make sure the remote revisions
559
# have been pulled into the local branch. We may change that
560
# behavior in the future.
561
self.failUnless(self.tree.branch.repository.has_revision('new_r3'))
563
def test_no_commits(self):
564
new_tree = self.make_branch_and_tree('new_tree')
565
self.assertRaises(errors.NoCommits,
566
self.get_in_history, 'branch:new_tree')
568
def test_as_revision_id(self):
569
self.assertAsRevisionId('alt_r2', 'branch:tree2')
572
class TestRevisionSpec_submit(TestRevisionSpec):
574
def test_submit_branch(self):
575
# Common ancestor of trees is 'alt_r2'
576
self.assertRaises(errors.NoSubmitBranch, self.get_in_history,
578
self.tree.branch.set_parent('../tree2')
579
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
580
self.tree.branch.set_parent('bogus')
581
self.assertRaises(errors.NotBranchError, self.get_in_history,
583
# submit branch overrides parent branch
584
self.tree.branch.set_submit_branch('tree2')
585
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
587
def test_as_revision_id(self):
588
self.tree.branch.set_submit_branch('tree2')
589
self.assertAsRevisionId('alt_r2', 'branch:tree2')