1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
1
# Copyright (C) 2004, 2005 by 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
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')
180
def test_negative_int(self):
181
self.assertInHistoryIs(2, 'r2', '-1')
182
self.assertInHistoryIs(1, 'r1', '-2')
184
self.assertInHistoryIs(1, 'r1', '-3')
185
self.assertInHistoryIs(1, 'r1', '-4')
186
self.assertInHistoryIs(1, 'r1', '-100')
188
def test_positive(self):
189
self.assertInHistoryIs(0, 'null:', 'revno:0')
190
self.assertInHistoryIs(1, 'r1', 'revno:1')
191
self.assertInHistoryIs(2, 'r2', 'revno:2')
193
self.assertInvalid('revno:3')
195
def test_negative(self):
196
self.assertInHistoryIs(2, 'r2', 'revno:-1')
197
self.assertInHistoryIs(1, 'r1', 'revno:-2')
199
self.assertInHistoryIs(1, 'r1', 'revno:-3')
200
self.assertInHistoryIs(1, 'r1', 'revno:-4')
202
def test_invalid_number(self):
203
# Get the right exception text
206
except ValueError, e:
208
self.assertInvalid('revno:X', extra='\n' + str(e))
210
def test_missing_number_and_branch(self):
211
self.assertInvalid('revno::',
212
extra='\ncannot have an empty revno and no branch')
214
def test_invalid_number_with_branch(self):
217
except ValueError, e:
219
self.assertInvalid('revno:X:tree2', extra='\n' + str(e))
221
def test_non_exact_branch(self):
222
# It seems better to require an exact path to the branch
223
# Branch.open() rather than using Branch.open_containing()
224
spec = RevisionSpec.from_string('revno:2:tree2/a')
225
self.assertRaises(errors.NotBranchError,
226
spec.in_history, self.tree.branch)
228
def test_with_branch(self):
229
# Passing a URL overrides the supplied branch path
230
revinfo = self.get_in_history('revno: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_int_with_branch(self):
237
revinfo = self.get_in_history('2:tree2')
238
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
239
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
240
self.assertEqual(2, revinfo.revno)
241
self.assertEqual('alt_r2', revinfo.rev_id)
243
def test_with_url(self):
244
url = self.get_url() + '/tree2'
245
revinfo = self.get_in_history('revno:2:%s' % (url,))
246
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
247
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
248
self.assertEqual(2, revinfo.revno)
249
self.assertEqual('alt_r2', revinfo.rev_id)
251
def test_negative_with_url(self):
252
url = self.get_url() + '/tree2'
253
revinfo = self.get_in_history('revno:-1:%s' % (url,))
254
self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
255
self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
256
self.assertEqual(2, revinfo.revno)
257
self.assertEqual('alt_r2', revinfo.rev_id)
259
def test_different_history_lengths(self):
260
# Make sure we use the revisions and offsets in the supplied branch
261
# not the ones in the original branch.
262
self.tree2.commit('three', rev_id='r3')
263
self.assertInHistoryIs(3, 'r3', 'revno:3:tree2')
264
self.assertInHistoryIs(3, 'r3', 'revno:-1:tree2')
266
def test_invalid_branch(self):
267
self.assertRaises(errors.NotBranchError,
268
self.get_in_history, 'revno:-1:tree3')
270
def test_invalid_revno_in_branch(self):
271
self.tree.commit('three', rev_id='r3')
272
self.assertInvalid('revno:3:tree2')
274
def test_revno_n_path(self):
275
"""Old revno:N:path tests"""
276
wta = self.make_branch_and_tree('a')
279
wta.commit('Commit one', rev_id='a@r-0-1')
280
wta.commit('Commit two', rev_id='a@r-0-2')
281
wta.commit('Commit three', rev_id='a@r-0-3')
283
wtb = self.make_branch_and_tree('b')
286
wtb.commit('Commit one', rev_id='b@r-0-1')
287
wtb.commit('Commit two', rev_id='b@r-0-2')
288
wtb.commit('Commit three', rev_id='b@r-0-3')
291
self.assertEqual((1, 'a@r-0-1'),
292
spec_in_history('revno:1:a/', ba))
293
# The argument of in_history should be ignored since it is
294
# redundant with the path in the spec.
295
self.assertEqual((1, 'a@r-0-1'),
296
spec_in_history('revno:1:a/', None))
297
self.assertEqual((1, 'a@r-0-1'),
298
spec_in_history('revno:1:a/', bb))
299
self.assertEqual((2, 'b@r-0-2'),
300
spec_in_history('revno:2:b/', None))
302
def test_as_revision_id(self):
303
self.assertAsRevisionId('null:', '0')
304
self.assertAsRevisionId('r1', '1')
305
self.assertAsRevisionId('r2', '2')
306
self.assertAsRevisionId('r1', '-2')
307
self.assertAsRevisionId('r2', '-1')
308
self.assertAsRevisionId('alt_r2', '1.1.1')
310
def test_as_tree(self):
311
tree = self.get_as_tree('0')
312
self.assertEquals(_mod_revision.NULL_REVISION, tree.get_revision_id())
313
tree = self.get_as_tree('1')
314
self.assertEquals('r1', tree.get_revision_id())
315
tree = self.get_as_tree('2')
316
self.assertEquals('r2', tree.get_revision_id())
317
tree = self.get_as_tree('-2')
318
self.assertEquals('r1', tree.get_revision_id())
319
tree = self.get_as_tree('-1')
320
self.assertEquals('r2', tree.get_revision_id())
321
tree = self.get_as_tree('1.1.1')
322
self.assertEquals('alt_r2', tree.get_revision_id())
325
class TestRevisionSpec_revid(TestRevisionSpec):
327
def test_in_history(self):
328
# We should be able to access revisions that are directly
330
self.assertInHistoryIs(1, 'r1', 'revid:r1')
331
self.assertInHistoryIs(2, 'r2', 'revid:r2')
333
def test_missing(self):
334
self.assertInvalid('revid:r3', invalid_as_revision_id=False)
336
def test_merged(self):
337
"""We can reach revisions in the ancestry"""
338
self.assertInHistoryIs(None, 'alt_r2', 'revid:alt_r2')
340
def test_not_here(self):
341
self.tree2.commit('alt third', rev_id='alt_r3')
342
# It exists in tree2, but not in tree
343
self.assertInvalid('revid:alt_r3', invalid_as_revision_id=False)
345
def test_in_repository(self):
346
"""We can get any revision id in the repository"""
347
# XXX: This may change in the future, but for now, it is true
348
self.tree2.commit('alt third', rev_id='alt_r3')
349
self.tree.branch.repository.fetch(self.tree2.branch.repository,
350
revision_id='alt_r3')
351
self.assertInHistoryIs(None, 'alt_r3', 'revid:alt_r3')
353
def test_unicode(self):
354
"""We correctly convert a unicode ui string to an encoded revid."""
355
revision_id = u'\N{SNOWMAN}'.encode('utf-8')
356
self.tree.commit('unicode', rev_id=revision_id)
357
self.assertInHistoryIs(3, revision_id, u'revid:\N{SNOWMAN}')
358
self.assertInHistoryIs(3, revision_id, 'revid:' + revision_id)
360
def test_as_revision_id(self):
361
self.assertAsRevisionId('r1', 'revid:r1')
362
self.assertAsRevisionId('r2', 'revid:r2')
363
self.assertAsRevisionId('alt_r2', 'revid:alt_r2')
366
class TestRevisionSpec_last(TestRevisionSpec):
368
def test_positive(self):
369
self.assertInHistoryIs(2, 'r2', 'last:1')
370
self.assertInHistoryIs(1, 'r1', 'last:2')
371
self.assertInHistoryIs(0, 'null:', 'last:3')
373
def test_empty(self):
374
self.assertInHistoryIs(2, 'r2', 'last:')
376
def test_negative(self):
377
self.assertInvalid('last:-1',
378
extra='\nyou must supply a positive value')
380
def test_missing(self):
381
self.assertInvalid('last:4')
383
def test_no_history(self):
384
tree = self.make_branch_and_tree('tree3')
386
self.assertRaises(errors.NoCommits,
387
spec_in_history, 'last:', tree.branch)
389
def test_not_a_number(self):
392
except ValueError, e:
394
self.assertInvalid('last:Y', extra='\n' + str(e))
396
def test_as_revision_id(self):
397
self.assertAsRevisionId('r2', 'last:1')
398
self.assertAsRevisionId('r1', 'last:2')
401
class TestRevisionSpec_before(TestRevisionSpec):
404
self.assertInHistoryIs(1, 'r1', 'before:2')
405
self.assertInHistoryIs(1, 'r1', 'before:-1')
407
def test_before_one(self):
408
self.assertInHistoryIs(0, 'null:', 'before:1')
410
def test_before_none(self):
411
self.assertInvalid('before:0',
412
extra='\ncannot go before the null: revision')
414
def test_revid(self):
415
self.assertInHistoryIs(1, 'r1', 'before:revid:r2')
418
self.assertInHistoryIs(1, 'r1', 'before:last:1')
420
def test_alt_revid(self):
421
# This will grab the left-most ancestor for alternate histories
422
self.assertInHistoryIs(1, 'r1', 'before:revid:alt_r2')
424
def test_alt_no_parents(self):
425
new_tree = self.make_branch_and_tree('new_tree')
426
new_tree.commit('first', rev_id='new_r1')
427
self.tree.branch.repository.fetch(new_tree.branch.repository,
428
revision_id='new_r1')
429
self.assertInHistoryIs(0, 'null:', 'before:revid:new_r1')
431
def test_as_revision_id(self):
432
self.assertAsRevisionId('r1', 'before:revid:r2')
433
self.assertAsRevisionId('r1', 'before:2')
434
self.assertAsRevisionId('r1', 'before:1.1.1')
435
self.assertAsRevisionId('r1', 'before:revid:alt_r2')
438
class TestRevisionSpec_tag(TestRevisionSpec):
440
def make_branch_and_tree(self, relpath):
441
# override format as the default one may not support tags
442
return TestRevisionSpec.make_branch_and_tree(
443
self, relpath, format='dirstate-tags')
445
def test_from_string_tag(self):
446
spec = RevisionSpec.from_string('tag:bzr-0.14')
447
self.assertIsInstance(spec, RevisionSpec_tag)
448
self.assertEqual(spec.spec, 'bzr-0.14')
450
def test_lookup_tag(self):
451
self.tree.branch.tags.set_tag('bzr-0.14', 'r1')
452
self.assertInHistoryIs(1, 'r1', 'tag:bzr-0.14')
453
self.tree.branch.tags.set_tag('null_rev', 'null:')
454
self.assertInHistoryIs(0, 'null:', 'tag:null_rev')
456
def test_failed_lookup(self):
457
# tags that don't exist give a specific message: arguably we should
458
# just give InvalidRevisionSpec but I think this is more helpful
459
self.assertRaises(errors.NoSuchTag,
461
'tag:some-random-tag')
463
def test_as_revision_id(self):
464
self.tree.branch.tags.set_tag('my-tag', 'r2')
465
self.tree.branch.tags.set_tag('null_rev', 'null:')
466
self.assertAsRevisionId('r2', 'tag:my-tag')
467
self.assertAsRevisionId('null:', 'tag:null_rev')
468
self.assertAsRevisionId('r1', 'before:tag:my-tag')
471
class TestRevisionSpec_date(TestRevisionSpec):
474
super(TestRevisionSpec, self).setUp()
476
new_tree = self.make_branch_and_tree('new_tree')
477
new_tree.commit('Commit one', rev_id='new_r1',
478
timestamp=time.time() - 60*60*24)
479
new_tree.commit('Commit two', rev_id='new_r2')
480
new_tree.commit('Commit three', rev_id='new_r3')
484
def test_tomorrow(self):
485
self.assertInvalid('date:tomorrow')
487
def test_today(self):
488
self.assertInHistoryIs(2, 'new_r2', 'date:today')
489
self.assertInHistoryIs(1, 'new_r1', 'before:date:today')
491
def test_yesterday(self):
492
self.assertInHistoryIs(1, 'new_r1', 'date:yesterday')
494
def test_invalid(self):
495
self.assertInvalid('date:foobar', extra='\ninvalid date')
496
# You must have '-' between year/month/day
497
self.assertInvalid('date:20040404', extra='\ninvalid date')
498
# Need 2 digits for each date piece
499
self.assertInvalid('date:2004-4-4', extra='\ninvalid date')
502
now = datetime.datetime.now()
503
self.assertInHistoryIs(2, 'new_r2',
504
'date:%04d-%02d-%02d' % (now.year, now.month, now.day))
506
def test_as_revision_id(self):
507
self.assertAsRevisionId('new_r2', 'date:today')
510
class TestRevisionSpec_ancestor(TestRevisionSpec):
512
def test_non_exact_branch(self):
513
# It seems better to require an exact path to the branch
514
# Branch.open() rather than using Branch.open_containing()
515
self.assertRaises(errors.NotBranchError,
516
self.get_in_history, 'ancestor:tree2/a')
518
def test_simple(self):
519
# Common ancestor of trees is 'alt_r2'
520
self.assertInHistoryIs(None, 'alt_r2', 'ancestor:tree2')
522
# Going the other way, we get a valid revno
524
self.tree = self.tree2
526
self.assertInHistoryIs(2, 'alt_r2', 'ancestor:tree')
529
self.assertInHistoryIs(2, 'r2', 'ancestor:tree')
531
def test_unrelated(self):
532
new_tree = self.make_branch_and_tree('new_tree')
534
new_tree.commit('Commit one', rev_id='new_r1')
535
new_tree.commit('Commit two', rev_id='new_r2')
536
new_tree.commit('Commit three', rev_id='new_r3')
538
# With no common ancestor, we should raise another user error
539
self.assertRaises(errors.NoCommonAncestor,
540
self.get_in_history, 'ancestor:new_tree')
542
def test_no_commits(self):
543
new_tree = self.make_branch_and_tree('new_tree')
544
self.assertRaises(errors.NoCommits,
545
spec_in_history, 'ancestor:new_tree',
548
self.assertRaises(errors.NoCommits,
549
spec_in_history, 'ancestor:tree',
552
def test_as_revision_id(self):
553
self.assertAsRevisionId('alt_r2', 'ancestor:tree2')
556
class TestRevisionSpec_branch(TestRevisionSpec):
558
def test_non_exact_branch(self):
559
# It seems better to require an exact path to the branch
560
# Branch.open() rather than using Branch.open_containing()
561
self.assertRaises(errors.NotBranchError,
562
self.get_in_history, 'branch:tree2/a')
564
def test_simple(self):
565
self.assertInHistoryIs(None, 'alt_r2', 'branch:tree2')
568
self.assertInHistoryIs(2, 'r2', 'branch:tree')
570
def test_unrelated(self):
571
new_tree = self.make_branch_and_tree('new_tree')
573
new_tree.commit('Commit one', rev_id='new_r1')
574
new_tree.commit('Commit two', rev_id='new_r2')
575
new_tree.commit('Commit three', rev_id='new_r3')
577
self.assertInHistoryIs(None, 'new_r3', 'branch:new_tree')
579
# XXX: Right now, we use fetch() to make sure the remote revisions
580
# have been pulled into the local branch. We may change that
581
# behavior in the future.
582
self.failUnless(self.tree.branch.repository.has_revision('new_r3'))
584
def test_no_commits(self):
585
new_tree = self.make_branch_and_tree('new_tree')
586
self.assertRaises(errors.NoCommits,
587
self.get_in_history, 'branch:new_tree')
588
self.assertRaises(errors.NoCommits,
589
self.get_as_tree, 'branch:new_tree')
591
def test_as_revision_id(self):
592
self.assertAsRevisionId('alt_r2', 'branch:tree2')
594
def test_as_tree(self):
595
tree = self.get_as_tree('branch:tree', self.tree2)
596
self.assertEquals('r2', tree.get_revision_id())
597
self.assertFalse(self.tree2.branch.repository.has_revision('r2'))
600
class TestRevisionSpec_submit(TestRevisionSpec):
602
def test_submit_branch(self):
603
# Common ancestor of trees is 'alt_r2'
604
self.assertRaises(errors.NoSubmitBranch, self.get_in_history,
606
self.tree.branch.set_parent('../tree2')
607
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
608
self.tree.branch.set_parent('bogus')
609
self.assertRaises(errors.NotBranchError, self.get_in_history,
611
# submit branch overrides parent branch
612
self.tree.branch.set_submit_branch('tree2')
613
self.assertInHistoryIs(None, 'alt_r2', 'submit:')
615
def test_as_revision_id(self):
616
self.tree.branch.set_submit_branch('tree2')
617
self.assertAsRevisionId('alt_r2', 'branch:tree2')
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'))