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
# 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.assertEquals(RevisionSpec('date:yesterday').in_history(b),
55
self.assertEquals(RevisionSpec('before:date:today').in_history(b),
58
self.assertEquals(RevisionSpec('last:1').in_history(b),
60
self.assertEquals(RevisionSpec('-1').in_history(b), (3, 'a@r-0-3'))
61
# self.assertEquals(b.get_revision_info('last:1'), (3, 'a@r-0-3'))
62
# self.assertEquals(b.get_revision_info('-1'), (3, 'a@r-0-3'))
64
self.assertEquals(RevisionSpec('ancestor:.').in_history(b).rev_id,
68
wt2 = self.make_branch_and_tree('newbranch')
70
self.assertRaises(NoCommits, RevisionSpec('ancestor:.').in_history, b2)
72
d3 = b.bzrdir.sprout('copy')
74
wt3 = d3.open_workingtree()
75
wt3.commit('Commit four', rev_id='b@r-0-4')
76
self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
78
merge(['copy', -1], [None, None])
79
wt.commit('Commit five', rev_id='a@r-0-4')
80
self.assertEquals(RevisionSpec('ancestor:copy').in_history(b).rev_id,
82
self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
85
# This should be in the revision store, but not in revision-history
86
self.assertEquals((None, 'b@r-0-4'),
87
RevisionSpec('revid:b@r-0-4').in_history(b))
89
def test_branch_namespace(self):
90
"""Ensure that the branch namespace pulls in the requisite content."""
91
self.build_tree(['branch1/', 'branch1/file', 'branch2/'])
92
wt = self.make_branch_and_tree('branch1')
96
d2 = branch.bzrdir.sprout('branch2')
97
print >> open('branch2/file', 'w'), 'new content'
98
branch2 = d2.open_branch()
99
d2.open_workingtree().commit('update file', rev_id='A')
100
spec = RevisionSpec('branch:./branch2/.bzr/../')
101
rev_info = spec.in_history(branch)
102
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())
149
def test_unregistered_spec(self):
150
self.assertRaises(errors.NoSuchRevisionSpec,
151
RevisionSpec.from_string, 'foo')
152
self.assertRaises(errors.NoSuchRevisionSpec,
153
RevisionSpec.from_string, '123a')
157
class TestRevnoFromString(TestCase):
159
def test_from_string_dotted_decimal(self):
160
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '-1.1')
161
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '.1')
162
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1..1')
163
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1.2..1')
164
self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1.')
165
self.assertIsInstance(RevisionSpec.from_string('1.1'), RevisionSpec_revno)
166
self.assertIsInstance(RevisionSpec.from_string('1.1.3'), RevisionSpec_revno)
169
class TestRevisionSpec_revno(TestRevisionSpec):
171
def test_positive_int(self):
172
self.assertInHistoryIs(0, 'null:', '0')
173
self.assertInHistoryIs(1, 'r1', '1')
174
self.assertInHistoryIs(2, 'r2', '2')
175
self.assertInvalid('3')
177
def test_dotted_decimal(self):
178
self.assertInHistoryIs(None, 'alt_r2', '1.1.1')
179
self.assertInvalid('1.1.123')
181
def test_negative_int(self):
182
self.assertInHistoryIs(2, 'r2', '-1')
183
self.assertInHistoryIs(1, 'r1', '-2')
185
self.assertInHistoryIs(1, 'r1', '-3')
186
self.assertInHistoryIs(1, 'r1', '-4')
187
self.assertInHistoryIs(1, 'r1', '-100')
189
def test_positive(self):
190
self.assertInHistoryIs(0, 'null:', 'revno:0')
191
self.assertInHistoryIs(1, 'r1', 'revno:1')
192
self.assertInHistoryIs(2, 'r2', 'revno:2')
194
self.assertInvalid('revno:3')
196
def test_negative(self):
197
self.assertInHistoryIs(2, 'r2', 'revno:-1')
198
self.assertInHistoryIs(1, 'r1', 'revno:-2')
200
self.assertInHistoryIs(1, 'r1', 'revno:-3')
201
self.assertInHistoryIs(1, 'r1', 'revno:-4')
203
def test_invalid_number(self):
204
# Get the right exception text
207
except ValueError, e:
209
self.assertInvalid('revno:X', extra='\n' + str(e))
211
def test_missing_number_and_branch(self):
212
self.assertInvalid('revno::',
213
extra='\ncannot have an empty revno and no branch')
215
def test_invalid_number_with_branch(self):
218
except ValueError, e:
220
self.assertInvalid('revno:X:tree2', extra='\n' + str(e))
222
def test_non_exact_branch(self):
223
# It seems better to require an exact path to the branch
224
# Branch.open() rather than using Branch.open_containing()
225
spec = RevisionSpec.from_string('revno:2:tree2/a')
226
self.assertRaises(errors.NotBranchError,
227
spec.in_history, self.tree.branch)
229
def test_with_branch(self):
230
# Passing a URL overrides the supplied branch path
231
revinfo = self.get_in_history('revno:2:tree2')
232
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
233
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
234
self.assertEqual(2, revinfo.revno)
235
self.assertEqual('alt_r2', revinfo.rev_id)
237
def test_int_with_branch(self):
238
revinfo = self.get_in_history('2:tree2')
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_with_url(self):
245
url = self.get_url() + '/tree2'
246
revinfo = self.get_in_history('revno:2:%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_negative_with_url(self):
253
url = self.get_url() + '/tree2'
254
revinfo = self.get_in_history('revno:-1:%s' % (url,))
255
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
256
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
257
self.assertEqual(2, revinfo.revno)
258
self.assertEqual('alt_r2', revinfo.rev_id)
260
def test_different_history_lengths(self):
261
# Make sure we use the revisions and offsets in the supplied branch
262
# not the ones in the original branch.
263
self.tree2.commit('three', rev_id='r3')
264
self.assertInHistoryIs(3, 'r3', 'revno:3:tree2')
265
self.assertInHistoryIs(3, 'r3', 'revno:-1:tree2')
267
def test_invalid_branch(self):
268
self.assertRaises(errors.NotBranchError,
269
self.get_in_history, 'revno:-1:tree3')
271
def test_invalid_revno_in_branch(self):
272
self.tree.commit('three', rev_id='r3')
273
self.assertInvalid('revno:3:tree2')
275
def test_revno_n_path(self):
276
"""Old revno:N:path tests"""
277
wta = self.make_branch_and_tree('a')
280
wta.commit('Commit one', rev_id='a@r-0-1')
281
wta.commit('Commit two', rev_id='a@r-0-2')
282
wta.commit('Commit three', rev_id='a@r-0-3')
284
wtb = self.make_branch_and_tree('b')
287
wtb.commit('Commit one', rev_id='b@r-0-1')
288
wtb.commit('Commit two', rev_id='b@r-0-2')
289
wtb.commit('Commit three', rev_id='b@r-0-3')
292
self.assertEqual((1, 'a@r-0-1'),
293
spec_in_history('revno:1:a/', ba))
294
# The argument of in_history should be ignored since it is
295
# redundant with the path in the spec.
296
self.assertEqual((1, 'a@r-0-1'),
297
spec_in_history('revno:1:a/', None))
298
self.assertEqual((1, 'a@r-0-1'),
299
spec_in_history('revno:1:a/', bb))
300
self.assertEqual((2, 'b@r-0-2'),
301
spec_in_history('revno:2:b/', None))
303
def test_as_revision_id(self):
304
self.assertAsRevisionId('null:', '0')
305
self.assertAsRevisionId('r1', '1')
306
self.assertAsRevisionId('r2', '2')
307
self.assertAsRevisionId('r1', '-2')
308
self.assertAsRevisionId('r2', '-1')
309
self.assertAsRevisionId('alt_r2', '1.1.1')
311
def test_as_tree(self):
312
tree = self.get_as_tree('0')
313
self.assertEquals(_mod_revision.NULL_REVISION, tree.get_revision_id())
314
tree = self.get_as_tree('1')
315
self.assertEquals('r1', tree.get_revision_id())
316
tree = self.get_as_tree('2')
317
self.assertEquals('r2', tree.get_revision_id())
318
tree = self.get_as_tree('-2')
319
self.assertEquals('r1', tree.get_revision_id())
320
tree = self.get_as_tree('-1')
321
self.assertEquals('r2', tree.get_revision_id())
322
tree = self.get_as_tree('1.1.1')
323
self.assertEquals('alt_r2', tree.get_revision_id())
326
class TestRevisionSpec_revid(TestRevisionSpec):
328
def test_in_history(self):
329
# We should be able to access revisions that are directly
331
self.assertInHistoryIs(1, 'r1', 'revid:r1')
332
self.assertInHistoryIs(2, 'r2', 'revid:r2')
334
def test_missing(self):
335
self.assertInvalid('revid:r3', invalid_as_revision_id=False)
337
def test_merged(self):
338
"""We can reach revisions in the ancestry"""
339
self.assertInHistoryIs(None, 'alt_r2', 'revid:alt_r2')
341
def test_not_here(self):
342
self.tree2.commit('alt third', rev_id='alt_r3')
343
# It exists in tree2, but not in tree
344
self.assertInvalid('revid:alt_r3', invalid_as_revision_id=False)
346
def test_in_repository(self):
347
"""We can get any revision id in the repository"""
348
# XXX: This may change in the future, but for now, it is true
349
self.tree2.commit('alt third', rev_id='alt_r3')
350
self.tree.branch.repository.fetch(self.tree2.branch.repository,
351
revision_id='alt_r3')
352
self.assertInHistoryIs(None, 'alt_r3', 'revid:alt_r3')
354
def test_unicode(self):
355
"""We correctly convert a unicode ui string to an encoded revid."""
356
revision_id = u'\N{SNOWMAN}'.encode('utf-8')
357
self.tree.commit('unicode', rev_id=revision_id)
358
self.assertInHistoryIs(3, revision_id, u'revid:\N{SNOWMAN}')
359
self.assertInHistoryIs(3, revision_id, 'revid:' + revision_id)
361
def test_as_revision_id(self):
362
self.assertAsRevisionId('r1', 'revid:r1')
363
self.assertAsRevisionId('r2', 'revid:r2')
364
self.assertAsRevisionId('alt_r2', 'revid:alt_r2')
367
class TestRevisionSpec_last(TestRevisionSpec):
369
def test_positive(self):
370
self.assertInHistoryIs(2, 'r2', 'last:1')
371
self.assertInHistoryIs(1, 'r1', 'last:2')
372
self.assertInHistoryIs(0, 'null:', 'last:3')
374
def test_empty(self):
375
self.assertInHistoryIs(2, 'r2', 'last:')
377
def test_negative(self):
378
self.assertInvalid('last:-1',
379
extra='\nyou must supply a positive value')
381
def test_missing(self):
382
self.assertInvalid('last:4')
384
def test_no_history(self):
385
tree = self.make_branch_and_tree('tree3')
387
self.assertRaises(errors.NoCommits,
388
spec_in_history, 'last:', tree.branch)
390
def test_not_a_number(self):
393
except ValueError, e:
395
self.assertInvalid('last:Y', extra='\n' + str(e))
397
def test_as_revision_id(self):
398
self.assertAsRevisionId('r2', 'last:1')
399
self.assertAsRevisionId('r1', 'last:2')
402
class TestRevisionSpec_before(TestRevisionSpec):
405
self.assertInHistoryIs(1, 'r1', 'before:2')
406
self.assertInHistoryIs(1, 'r1', 'before:-1')
408
def test_before_one(self):
409
self.assertInHistoryIs(0, 'null:', 'before:1')
411
def test_before_none(self):
412
self.assertInvalid('before:0',
413
extra='\ncannot go before the null: revision')
415
def test_revid(self):
416
self.assertInHistoryIs(1, 'r1', 'before:revid:r2')
419
self.assertInHistoryIs(1, 'r1', 'before:last:1')
421
def test_alt_revid(self):
422
# This will grab the left-most ancestor for alternate histories
423
self.assertInHistoryIs(1, 'r1', 'before:revid:alt_r2')
425
def test_alt_no_parents(self):
426
new_tree = self.make_branch_and_tree('new_tree')
427
new_tree.commit('first', rev_id='new_r1')
428
self.tree.branch.repository.fetch(new_tree.branch.repository,
429
revision_id='new_r1')
430
self.assertInHistoryIs(0, 'null:', 'before:revid:new_r1')
432
def test_as_revision_id(self):
433
self.assertAsRevisionId('r1', 'before:revid:r2')
434
self.assertAsRevisionId('r1', 'before:2')
435
self.assertAsRevisionId('r1', 'before:1.1.1')
436
self.assertAsRevisionId('r1', 'before:revid:alt_r2')
439
class TestRevisionSpec_tag(TestRevisionSpec):
441
def make_branch_and_tree(self, relpath):
442
# override format as the default one may not support tags
443
return TestRevisionSpec.make_branch_and_tree(
444
self, relpath, format='dirstate-tags')
446
def test_from_string_tag(self):
447
spec = RevisionSpec.from_string('tag:bzr-0.14')
448
self.assertIsInstance(spec, RevisionSpec_tag)
449
self.assertEqual(spec.spec, 'bzr-0.14')
451
def test_lookup_tag(self):
452
self.tree.branch.tags.set_tag('bzr-0.14', 'r1')
453
self.assertInHistoryIs(1, 'r1', 'tag:bzr-0.14')
454
self.tree.branch.tags.set_tag('null_rev', 'null:')
455
self.assertInHistoryIs(0, 'null:', 'tag:null_rev')
457
def test_failed_lookup(self):
458
# tags that don't exist give a specific message: arguably we should
459
# just give InvalidRevisionSpec but I think this is more helpful
460
self.assertRaises(errors.NoSuchTag,
462
'tag:some-random-tag')
464
def test_as_revision_id(self):
465
self.tree.branch.tags.set_tag('my-tag', 'r2')
466
self.tree.branch.tags.set_tag('null_rev', 'null:')
467
self.assertAsRevisionId('r2', 'tag:my-tag')
468
self.assertAsRevisionId('null:', 'tag:null_rev')
469
self.assertAsRevisionId('r1', 'before:tag:my-tag')
472
class TestRevisionSpec_date(TestRevisionSpec):
475
super(TestRevisionSpec, self).setUp()
477
new_tree = self.make_branch_and_tree('new_tree')
478
new_tree.commit('Commit one', rev_id='new_r1',
479
timestamp=time.time() - 60*60*24)
480
new_tree.commit('Commit two', rev_id='new_r2')
481
new_tree.commit('Commit three', rev_id='new_r3')
485
def test_tomorrow(self):
486
self.assertInvalid('date:tomorrow')
488
def test_today(self):
489
self.assertInHistoryIs(2, 'new_r2', 'date:today')
490
self.assertInHistoryIs(1, 'new_r1', 'before:date:today')
492
def test_yesterday(self):
493
self.assertInHistoryIs(1, 'new_r1', 'date:yesterday')
495
def test_invalid(self):
496
self.assertInvalid('date:foobar', extra='\ninvalid date')
497
# You must have '-' between year/month/day
498
self.assertInvalid('date:20040404', extra='\ninvalid date')
499
# Need 2 digits for each date piece
500
self.assertInvalid('date:2004-4-4', extra='\ninvalid date')
503
now = datetime.datetime.now()
504
self.assertInHistoryIs(2, 'new_r2',
505
'date:%04d-%02d-%02d' % (now.year, now.month, now.day))
507
def test_as_revision_id(self):
508
self.assertAsRevisionId('new_r2', 'date:today')
511
class TestRevisionSpec_ancestor(TestRevisionSpec):
513
def test_non_exact_branch(self):
514
# It seems better to require an exact path to the branch
515
# Branch.open() rather than using Branch.open_containing()
516
self.assertRaises(errors.NotBranchError,
517
self.get_in_history, 'ancestor:tree2/a')
519
def test_simple(self):
520
# Common ancestor of trees is 'alt_r2'
521
self.assertInHistoryIs(None, 'alt_r2', 'ancestor:tree2')
523
# Going the other way, we get a valid revno
525
self.tree = self.tree2
527
self.assertInHistoryIs(2, 'alt_r2', 'ancestor:tree')
530
self.assertInHistoryIs(2, 'r2', 'ancestor:tree')
532
def test_unrelated(self):
533
new_tree = self.make_branch_and_tree('new_tree')
535
new_tree.commit('Commit one', rev_id='new_r1')
536
new_tree.commit('Commit two', rev_id='new_r2')
537
new_tree.commit('Commit three', rev_id='new_r3')
539
# With no common ancestor, we should raise another user error
540
self.assertRaises(errors.NoCommonAncestor,
541
self.get_in_history, 'ancestor:new_tree')
543
def test_no_commits(self):
544
new_tree = self.make_branch_and_tree('new_tree')
545
self.assertRaises(errors.NoCommits,
546
spec_in_history, 'ancestor:new_tree',
549
self.assertRaises(errors.NoCommits,
550
spec_in_history, 'ancestor:tree',
553
def test_as_revision_id(self):
554
self.assertAsRevisionId('alt_r2', 'ancestor:tree2')
556
def test_default(self):
557
# We don't have a parent to default to
558
self.assertRaises(errors.NotBranchError, self.get_in_history,
561
# Create a branch with a parent to default to
562
tree3 = self.tree.bzrdir.sprout('tree3').open_workingtree()
563
tree3.commit('foo', rev_id='r3')
565
self.assertInHistoryIs(2, 'r2', 'ancestor:')
568
class TestRevisionSpec_branch(TestRevisionSpec):
570
def test_non_exact_branch(self):
571
# It seems better to require an exact path to the branch
572
# Branch.open() rather than using Branch.open_containing()
573
self.assertRaises(errors.NotBranchError,
574
self.get_in_history, 'branch:tree2/a')
576
def test_simple(self):
577
self.assertInHistoryIs(None, 'alt_r2', 'branch:tree2')
580
self.assertInHistoryIs(2, 'r2', 'branch:tree')
582
def test_unrelated(self):
583
new_tree = self.make_branch_and_tree('new_tree')
585
new_tree.commit('Commit one', rev_id='new_r1')
586
new_tree.commit('Commit two', rev_id='new_r2')
587
new_tree.commit('Commit three', rev_id='new_r3')
589
self.assertInHistoryIs(None, 'new_r3', 'branch:new_tree')
591
# XXX: Right now, we use fetch() to make sure the remote revisions
592
# have been pulled into the local branch. We may change that
593
# behavior in the future.
594
self.failUnless(self.tree.branch.repository.has_revision('new_r3'))
596
def test_no_commits(self):
597
new_tree = self.make_branch_and_tree('new_tree')
598
self.assertRaises(errors.NoCommits,
599
self.get_in_history, 'branch:new_tree')
600
self.assertRaises(errors.NoCommits,
601
self.get_as_tree, 'branch:new_tree')
603
def test_as_revision_id(self):
604
self.assertAsRevisionId('alt_r2', 'branch:tree2')
606
def test_as_tree(self):
607
tree = self.get_as_tree('branch:tree', self.tree2)
608
self.assertEquals('r2', tree.get_revision_id())
609
self.assertFalse(self.tree2.branch.repository.has_revision('r2'))
612
class TestRevisionSpec_submit(TestRevisionSpec):
614
def test_submit_branch(self):
615
# Common ancestor of trees is 'alt_r2'
616
self.assertRaises(errors.NoSubmitBranch, self.get_in_history,
618
self.tree.branch.set_parent('../tree2')
619
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
620
self.tree.branch.set_parent('bogus')
621
self.assertRaises(errors.NotBranchError, self.get_in_history,
623
# submit branch overrides parent branch
624
self.tree.branch.set_submit_branch('tree2')
625
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
627
def test_as_revision_id(self):
628
self.tree.branch.set_submit_branch('tree2')
629
self.assertAsRevisionId('alt_r2', 'branch:tree2')