~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_revisionnamespaces.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-02-01 23:48:08 UTC
  • mfrom: (2225.1.6 revert)
  • Revision ID: pqm@pqm.ubuntu.com-20070201234808-3b1302d73474bd8c
Display changes made by revert

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2006 by Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006 Canonical Ltd
2
2
#
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
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
16
16
 
 
17
import datetime
17
18
import os
18
19
import time
19
20
 
 
21
from bzrlib import (
 
22
    errors,
 
23
    )
20
24
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
26
 
 
27
 
 
28
 
class TestRevisionNamespaces(TestCaseWithTransport):
 
25
from bzrlib.tests import TestCase, TestCaseWithTransport
 
26
from bzrlib.revisionspec import RevisionSpec, RevisionSpec_revno
 
27
 
 
28
 
 
29
def spec_in_history(spec, branch):
 
30
    """A simple helper to change a revision spec into a branch search"""
 
31
    return RevisionSpec.from_string(spec).in_history(branch)
 
32
 
 
33
 
 
34
# Basic class, which just creates a really basic set of revisions
 
35
class TestRevisionSpec(TestCaseWithTransport):
 
36
 
 
37
    def setUp(self):
 
38
        super(TestRevisionSpec, self).setUp()
 
39
        # this sets up a revision graph:
 
40
        # r1: []             1
 
41
        # alt_r2: [r1]       1.1.1
 
42
        # r2: [r1, alt_r2]   2
 
43
 
 
44
        self.tree = self.make_branch_and_tree('tree')
 
45
        self.build_tree(['tree/a'])
 
46
        self.tree.add(['a'])
 
47
        self.tree.commit('a', rev_id='r1')
 
48
 
 
49
        self.tree2 = self.tree.bzrdir.sprout('tree2').open_workingtree()
 
50
        self.tree2.commit('alt', rev_id='alt_r2')
 
51
 
 
52
        self.tree.branch.repository.fetch(self.tree2.branch.repository,
 
53
                                          revision_id='alt_r2')
 
54
        self.tree.set_pending_merges(['alt_r2'])
 
55
        self.tree.commit('second', rev_id='r2')
 
56
 
 
57
    def get_in_history(self, revision_spec):
 
58
        return spec_in_history(revision_spec, self.tree.branch)
 
59
 
 
60
    def assertInHistoryIs(self, exp_revno, exp_revision_id, revision_spec):
 
61
        rev_info = self.get_in_history(revision_spec)
 
62
        self.assertEqual(exp_revno, rev_info.revno,
 
63
                         'Revision spec: %s returned wrong revno: %s != %s'
 
64
                         % (revision_spec, exp_revno, rev_info.revno))
 
65
        self.assertEqual(exp_revision_id, rev_info.rev_id,
 
66
                         'Revision spec: %s returned wrong revision id:'
 
67
                         ' %s != %s'
 
68
                         % (revision_spec, exp_revision_id, rev_info.rev_id))
 
69
 
 
70
    def assertInvalid(self, revision_spec, extra=''):
 
71
        try:
 
72
            self.get_in_history(revision_spec)
 
73
        except errors.InvalidRevisionSpec, e:
 
74
            self.assertEqual(revision_spec, e.spec)
 
75
            self.assertEqual(extra, e.extra)
 
76
        else:
 
77
            self.fail('Expected InvalidRevisionSpec to be raised for %s'
 
78
                      % (revision_spec,))
 
79
 
 
80
 
 
81
class TestOddRevisionSpec(TestRevisionSpec):
 
82
    """Test things that aren't normally thought of as revision specs"""
 
83
 
 
84
    def test_none(self):
 
85
        self.assertInHistoryIs(0, None, None)
 
86
 
 
87
    def test_object(self):
 
88
        self.assertRaises(TypeError, RevisionSpec.from_string, object())
 
89
 
 
90
    def test_unregistered_spec(self):
 
91
        self.assertRaises(errors.NoSuchRevisionSpec,
 
92
                          RevisionSpec.from_string, 'foo')
 
93
        self.assertRaises(errors.NoSuchRevisionSpec,
 
94
                          RevisionSpec.from_string, '123a')
 
95
 
 
96
 
 
97
 
 
98
class TestRevnoFromString(TestCase):
 
99
 
 
100
    def test_from_string_dotted_decimal(self):
 
101
        self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '-1.1')
 
102
        self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '.1')
 
103
        self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1..1')
 
104
        self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1.2..1')
 
105
        self.assertRaises(errors.NoSuchRevisionSpec, RevisionSpec.from_string, '1.')
 
106
        self.assertIsInstance(RevisionSpec.from_string('1.1'), RevisionSpec_revno)
 
107
        self.assertIsInstance(RevisionSpec.from_string('1.1.3'), RevisionSpec_revno)
 
108
 
 
109
 
 
110
class TestRevisionSpec_revno(TestRevisionSpec):
 
111
 
 
112
    def test_positive_int(self):
 
113
        self.assertInHistoryIs(0, None, '0')
 
114
        self.assertInHistoryIs(1, 'r1', '1')
 
115
        self.assertInHistoryIs(2, 'r2', '2')
 
116
        self.assertInvalid('3')
 
117
 
 
118
    def test_dotted_decimal(self):
 
119
        self.assertInHistoryIs(None, 'alt_r2', '1.1.1')
 
120
 
 
121
    def test_negative_int(self):
 
122
        self.assertInHistoryIs(2, 'r2', '-1')
 
123
        self.assertInHistoryIs(1, 'r1', '-2')
 
124
 
 
125
        self.assertInHistoryIs(1, 'r1', '-3')
 
126
        self.assertInHistoryIs(1, 'r1', '-4')
 
127
        self.assertInHistoryIs(1, 'r1', '-100')
 
128
 
 
129
    def test_positive(self):
 
130
        self.assertInHistoryIs(0, None, 'revno:0')
 
131
        self.assertInHistoryIs(1, 'r1', 'revno:1')
 
132
        self.assertInHistoryIs(2, 'r2', 'revno:2')
 
133
 
 
134
        self.assertInvalid('revno:3')
 
135
 
 
136
    def test_negative(self):
 
137
        self.assertInHistoryIs(2, 'r2', 'revno:-1')
 
138
        self.assertInHistoryIs(1, 'r1', 'revno:-2')
 
139
 
 
140
        self.assertInHistoryIs(1, 'r1', 'revno:-3')
 
141
        self.assertInHistoryIs(1, 'r1', 'revno:-4')
 
142
 
 
143
    def test_invalid_number(self):
 
144
        # Get the right exception text
 
145
        try:
 
146
            int('X')
 
147
        except ValueError, e:
 
148
            pass
 
149
        self.assertInvalid('revno:X', extra='\n' + str(e))
 
150
 
 
151
    def test_missing_number_and_branch(self):
 
152
        self.assertInvalid('revno::',
 
153
                           extra='\ncannot have an empty revno and no branch')
 
154
 
 
155
    def test_invalid_number_with_branch(self):
 
156
        try:
 
157
            int('X')
 
158
        except ValueError, e:
 
159
            pass
 
160
        self.assertInvalid('revno:X:tree2', extra='\n' + str(e))
 
161
 
 
162
    def test_non_exact_branch(self):
 
163
        # It seems better to require an exact path to the branch
 
164
        # Branch.open() rather than using Branch.open_containing()
 
165
        spec = RevisionSpec.from_string('revno:2:tree2/a')
 
166
        self.assertRaises(errors.NotBranchError,
 
167
                          spec.in_history, self.tree.branch)
 
168
 
 
169
    def test_with_branch(self):
 
170
        # Passing a URL overrides the supplied branch path
 
171
        revinfo = self.get_in_history('revno:2:tree2')
 
172
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
 
173
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
 
174
        self.assertEqual(2, revinfo.revno)
 
175
        self.assertEqual('alt_r2', revinfo.rev_id)
 
176
 
 
177
    def test_int_with_branch(self):
 
178
        revinfo = self.get_in_history('2:tree2')
 
179
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
 
180
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
 
181
        self.assertEqual(2, revinfo.revno)
 
182
        self.assertEqual('alt_r2', revinfo.rev_id)
 
183
 
 
184
    def test_with_url(self):
 
185
        url = self.get_url() + '/tree2'
 
186
        revinfo = self.get_in_history('revno:2:%s' % (url,))
 
187
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
 
188
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
 
189
        self.assertEqual(2, revinfo.revno)
 
190
        self.assertEqual('alt_r2', revinfo.rev_id)
 
191
 
 
192
    def test_negative_with_url(self):
 
193
        url = self.get_url() + '/tree2'
 
194
        revinfo = self.get_in_history('revno:-1:%s' % (url,))
 
195
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
 
196
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
 
197
        self.assertEqual(2, revinfo.revno)
 
198
        self.assertEqual('alt_r2', revinfo.rev_id)
 
199
 
 
200
    def test_different_history_lengths(self):
 
201
        # Make sure we use the revisions and offsets in the supplied branch
 
202
        # not the ones in the original branch.
 
203
        self.tree2.commit('three', rev_id='r3')
 
204
        self.assertInHistoryIs(3, 'r3', 'revno:3:tree2')
 
205
        self.assertInHistoryIs(3, 'r3', 'revno:-1:tree2')
 
206
 
 
207
    def test_invalid_branch(self):
 
208
        self.assertRaises(errors.NotBranchError,
 
209
                          self.get_in_history, 'revno:-1:tree3')
 
210
 
 
211
    def test_invalid_revno_in_branch(self):
 
212
        self.tree.commit('three', rev_id='r3')
 
213
        self.assertInvalid('revno:3:tree2')
29
214
 
30
215
    def test_revno_n_path(self):
31
 
        """Test revision specifiers.
32
 
 
33
 
        These identify revisions by date, etc."""
 
216
        """Old revno:N:path tests"""
34
217
        wta = self.make_branch_and_tree('a')
35
218
        ba = wta.branch
36
219
        
45
228
        wtb.commit('Commit two', rev_id='b@r-0-2')
46
229
        wtb.commit('Commit three', rev_id='b@r-0-3')
47
230
 
48
 
        self.assertEquals(RevisionSpec('revno:1:a/').in_history(ba),
49
 
                          (1, 'a@r-0-1'))
 
231
 
 
232
        self.assertEqual((1, 'a@r-0-1'),
 
233
                         spec_in_history('revno:1:a/', ba))
50
234
        # The argument of in_history should be ignored since it is
51
235
        # redundant with the path in the spec.
52
 
        self.assertEquals(RevisionSpec('revno:1:a/').in_history(None),
53
 
                          (1, 'a@r-0-1'))
54
 
        self.assertEquals(RevisionSpec('revno:1:a/').in_history(bb),
55
 
                          (1, 'a@r-0-1'))
56
 
        self.assertEquals(RevisionSpec('revno:2:b/').in_history(None),
57
 
                          (2, 'b@r-0-2'))
58
 
 
59
 
 
60
 
    def test_revision_namespaces(self):
61
 
        """Test revision specifiers.
62
 
 
63
 
        These identify revisions by date, etc."""
64
 
        wt = self.make_branch_and_tree('.')
65
 
        b = wt.branch
66
 
 
67
 
        wt.commit('Commit one', rev_id='a@r-0-1', timestamp=time.time() - 60*60*24)
68
 
        wt.commit('Commit two', rev_id='a@r-0-2')
69
 
        wt.commit('Commit three', rev_id='a@r-0-3')
70
 
 
71
 
        self.assertEquals(RevisionSpec(None).in_history(b), (0, None))
72
 
        self.assertEquals(RevisionSpec(1).in_history(b), (1, 'a@r-0-1'))
73
 
        self.assertEquals(RevisionSpec('revno:1').in_history(b),
74
 
                          (1, 'a@r-0-1'))
75
 
        self.assertEquals(RevisionSpec('revid:a@r-0-1').in_history(b),
76
 
                          (1, 'a@r-0-1'))
77
 
        self.assertRaises(NoSuchRevision,
78
 
                          RevisionSpec('revid:a@r-0-0').in_history, b)
79
 
        self.assertRaises(TypeError, RevisionSpec, object)
80
 
 
81
 
        self.assertEquals(RevisionSpec('date:today').in_history(b),
82
 
                          (2, 'a@r-0-2'))
83
 
        self.assertRaises(NoSuchRevision,
84
 
                          RevisionSpec('date:tomorrow').in_history, b)
85
 
        self.assertEquals(RevisionSpec('date:yesterday').in_history(b),
86
 
                          (1, 'a@r-0-1'))
87
 
        self.assertEquals(RevisionSpec('before:date:today').in_history(b),
88
 
                          (1, 'a@r-0-1'))
89
 
 
90
 
        self.assertEquals(RevisionSpec('last:1').in_history(b),
91
 
                          (3, 'a@r-0-3'))
92
 
        self.assertEquals(RevisionSpec('-1').in_history(b), (3, 'a@r-0-3'))
93
 
#        self.assertEquals(b.get_revision_info('last:1'), (3, 'a@r-0-3'))
94
 
#        self.assertEquals(b.get_revision_info('-1'), (3, 'a@r-0-3'))
95
 
 
96
 
        self.assertEquals(RevisionSpec('ancestor:.').in_history(b).rev_id,
97
 
                          'a@r-0-3')
98
 
 
99
 
        os.mkdir('newbranch')
100
 
        wt2 = self.make_branch_and_tree('newbranch')
101
 
        b2 = wt2.branch
102
 
        self.assertRaises(NoCommits, RevisionSpec('ancestor:.').in_history, b2)
103
 
 
104
 
        d3 = b.bzrdir.sprout('copy')
105
 
        b3 = d3.open_branch()
106
 
        wt3 = d3.open_workingtree()
107
 
        wt3.commit('Commit four', rev_id='b@r-0-4')
108
 
        self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
109
 
                          'a@r-0-3')
110
 
        merge(['copy', -1], [None, None])
111
 
        wt.commit('Commit five', rev_id='a@r-0-4')
112
 
        self.assertEquals(RevisionSpec('ancestor:copy').in_history(b).rev_id,
113
 
                          'b@r-0-4')
114
 
        self.assertEquals(RevisionSpec('ancestor:.').in_history(b3).rev_id,
115
 
                          'b@r-0-4')
116
 
 
117
 
        # This should be in the revision store, but not in revision-history
118
 
        self.assertEquals((None, 'b@r-0-4'),
119
 
                RevisionSpec('revid:b@r-0-4').in_history(b))
120
 
 
121
 
    def test_branch_namespace(self):
122
 
        """Ensure that the branch namespace pulls in the requisite content."""
123
 
        self.build_tree(['branch1/', 'branch1/file', 'branch2/'])
124
 
        wt = self.make_branch_and_tree('branch1')
125
 
        branch = wt.branch
126
 
        wt.add(['file'])
127
 
        wt.commit('add file')
128
 
        d2 = branch.bzrdir.sprout('branch2')
129
 
        print >> open('branch2/file', 'w'), 'new content'
130
 
        branch2 = d2.open_branch()
131
 
        d2.open_workingtree().commit('update file', rev_id='A')
132
 
        spec = RevisionSpec('branch:./branch2/.bzr/../')
133
 
        rev_info = spec.in_history(branch)
134
 
        self.assertEqual(rev_info, (None, 'A'))
135
 
 
 
236
        self.assertEqual((1, 'a@r-0-1'),
 
237
                         spec_in_history('revno:1:a/', None))
 
238
        self.assertEqual((1, 'a@r-0-1'),
 
239
                         spec_in_history('revno:1:a/', bb))
 
240
        self.assertEqual((2, 'b@r-0-2'),
 
241
                         spec_in_history('revno:2:b/', None))
 
242
 
 
243
 
 
244
 
 
245
class TestRevisionSpec_revid(TestRevisionSpec):
 
246
    
 
247
    def test_in_history(self):
 
248
        # We should be able to access revisions that are directly
 
249
        # in the history.
 
250
        self.assertInHistoryIs(1, 'r1', 'revid:r1')
 
251
        self.assertInHistoryIs(2, 'r2', 'revid:r2')
 
252
        
 
253
    def test_missing(self):
 
254
        self.assertInvalid('revid:r3')
 
255
 
 
256
    def test_merged(self):
 
257
        """We can reach revisions in the ancestry"""
 
258
        self.assertInHistoryIs(None, 'alt_r2', 'revid:alt_r2')
 
259
 
 
260
    def test_not_here(self):
 
261
        self.tree2.commit('alt third', rev_id='alt_r3')
 
262
        # It exists in tree2, but not in tree
 
263
        self.assertInvalid('revid:alt_r3')
 
264
 
 
265
    def test_in_repository(self):
 
266
        """We can get any revision id in the repository"""
 
267
        # XXX: This may change in the future, but for now, it is true
 
268
        self.tree2.commit('alt third', rev_id='alt_r3')
 
269
        self.tree.branch.repository.fetch(self.tree2.branch.repository,
 
270
                                          revision_id='alt_r3')
 
271
        self.assertInHistoryIs(None, 'alt_r3', 'revid:alt_r3')
 
272
 
 
273
 
 
274
class TestRevisionSpec_last(TestRevisionSpec):
 
275
 
 
276
    def test_positive(self):
 
277
        self.assertInHistoryIs(2, 'r2', 'last:1')
 
278
        self.assertInHistoryIs(1, 'r1', 'last:2')
 
279
        self.assertInHistoryIs(0, None, 'last:3')
 
280
 
 
281
    def test_empty(self):
 
282
        self.assertInHistoryIs(2, 'r2', 'last:')
 
283
 
 
284
    def test_negative(self):
 
285
        self.assertInvalid('last:-1',
 
286
                           extra='\nyou must supply a positive value')
 
287
 
 
288
    def test_missing(self):
 
289
        self.assertInvalid('last:4')
 
290
 
 
291
    def test_no_history(self):
 
292
        tree = self.make_branch_and_tree('tree3')
 
293
 
 
294
        self.assertRaises(errors.NoCommits,
 
295
                          spec_in_history, 'last:', tree.branch)
 
296
 
 
297
    def test_not_a_number(self):
 
298
        try:
 
299
            int('Y')
 
300
        except ValueError, e:
 
301
            pass
 
302
        self.assertInvalid('last:Y', extra='\n' + str(e))
 
303
 
 
304
 
 
305
class TestRevisionSpec_before(TestRevisionSpec):
 
306
 
 
307
    def test_int(self):
 
308
        self.assertInHistoryIs(1, 'r1', 'before:2')
 
309
        self.assertInHistoryIs(1, 'r1', 'before:-1')
 
310
 
 
311
    def test_before_one(self):
 
312
        self.assertInHistoryIs(0, None, 'before:1')
 
313
 
 
314
    def test_before_none(self):
 
315
        self.assertInvalid('before:0',
 
316
                           extra='\ncannot go before the null: revision')
 
317
 
 
318
    def test_revid(self):
 
319
        self.assertInHistoryIs(1, 'r1', 'before:revid:r2')
 
320
 
 
321
    def test_last(self):
 
322
        self.assertInHistoryIs(1, 'r1', 'before:last:1')
 
323
 
 
324
    def test_alt_revid(self):
 
325
        # This will grab the left-most ancestor for alternate histories
 
326
        self.assertInHistoryIs(1, 'r1', 'before:revid:alt_r2')
 
327
 
 
328
    def test_alt_no_parents(self):
 
329
        new_tree = self.make_branch_and_tree('new_tree')
 
330
        new_tree.commit('first', rev_id='new_r1')
 
331
        self.tree.branch.repository.fetch(new_tree.branch.repository,
 
332
                                          revision_id='new_r1')
 
333
        self.assertInHistoryIs(0, None, 'before:revid:new_r1')
 
334
 
 
335
 
 
336
class TestRevisionSpec_tag(TestRevisionSpec):
 
337
    
 
338
    def test_invalid(self):
 
339
        self.assertInvalid('tag:foo', extra='\ntag: namespace registered,'
 
340
                                            ' but not implemented')
 
341
 
 
342
 
 
343
class TestRevisionSpec_date(TestRevisionSpec):
 
344
 
 
345
    def setUp(self):
 
346
        super(TestRevisionSpec, self).setUp()
 
347
 
 
348
        new_tree = self.make_branch_and_tree('new_tree')
 
349
        new_tree.commit('Commit one', rev_id='new_r1',
 
350
                        timestamp=time.time() - 60*60*24)
 
351
        new_tree.commit('Commit two', rev_id='new_r2')
 
352
        new_tree.commit('Commit three', rev_id='new_r3')
 
353
 
 
354
        self.tree = new_tree
 
355
 
 
356
    def test_tomorrow(self):
 
357
        self.assertInvalid('date:tomorrow')
 
358
 
 
359
    def test_today(self):
 
360
        self.assertInHistoryIs(2, 'new_r2', 'date:today')
 
361
        self.assertInHistoryIs(1, 'new_r1', 'before:date:today')
 
362
 
 
363
    def test_yesterday(self):
 
364
        self.assertInHistoryIs(1, 'new_r1', 'date:yesterday')
 
365
 
 
366
    def test_invalid(self):
 
367
        self.assertInvalid('date:foobar', extra='\ninvalid date')
 
368
        # You must have '-' between year/month/day
 
369
        self.assertInvalid('date:20040404', extra='\ninvalid date')
 
370
        # Need 2 digits for each date piece
 
371
        self.assertInvalid('date:2004-4-4', extra='\ninvalid date')
 
372
 
 
373
    def test_day(self):
 
374
        now = datetime.datetime.now()
 
375
        self.assertInHistoryIs(2, 'new_r2',
 
376
            'date:%04d-%02d-%02d' % (now.year, now.month, now.day))
 
377
 
 
378
 
 
379
class TestRevisionSpec_ancestor(TestRevisionSpec):
 
380
    
 
381
    def test_non_exact_branch(self):
 
382
        # It seems better to require an exact path to the branch
 
383
        # Branch.open() rather than using Branch.open_containing()
 
384
        self.assertRaises(errors.NotBranchError,
 
385
                          self.get_in_history, 'ancestor:tree2/a')
 
386
 
 
387
    def test_simple(self):
 
388
        # Common ancestor of trees is 'alt_r2'
 
389
        self.assertInHistoryIs(None, 'alt_r2', 'ancestor:tree2')
 
390
 
 
391
        # Going the other way, we get a valid revno
 
392
        tmp = self.tree
 
393
        self.tree = self.tree2
 
394
        self.tree2 = tmp
 
395
        self.assertInHistoryIs(2, 'alt_r2', 'ancestor:tree')
 
396
 
 
397
    def test_self(self):
 
398
        self.assertInHistoryIs(2, 'r2', 'ancestor:tree')
 
399
 
 
400
    def test_unrelated(self):
 
401
        new_tree = self.make_branch_and_tree('new_tree')
 
402
 
 
403
        new_tree.commit('Commit one', rev_id='new_r1')
 
404
        new_tree.commit('Commit two', rev_id='new_r2')
 
405
        new_tree.commit('Commit three', rev_id='new_r3')
 
406
 
 
407
        # With no common ancestor, we should raise another user error
 
408
        self.assertRaises(errors.NoCommonAncestor,
 
409
                          self.get_in_history, 'ancestor:new_tree')
 
410
 
 
411
    def test_no_commits(self):
 
412
        new_tree = self.make_branch_and_tree('new_tree')
 
413
        self.assertRaises(errors.NoCommits,
 
414
                          spec_in_history, 'ancestor:new_tree',
 
415
                                           self.tree.branch)
 
416
                        
 
417
        self.assertRaises(errors.NoCommits,
 
418
                          spec_in_history, 'ancestor:tree',
 
419
                                           new_tree.branch)
 
420
 
 
421
 
 
422
class TestRevisionSpec_branch(TestRevisionSpec):
 
423
    
 
424
    def test_non_exact_branch(self):
 
425
        # It seems better to require an exact path to the branch
 
426
        # Branch.open() rather than using Branch.open_containing()
 
427
        self.assertRaises(errors.NotBranchError,
 
428
                          self.get_in_history, 'branch:tree2/a')
 
429
 
 
430
    def test_simple(self):
 
431
        self.assertInHistoryIs(None, 'alt_r2', 'branch:tree2')
 
432
 
 
433
    def test_self(self):
 
434
        self.assertInHistoryIs(2, 'r2', 'branch:tree')
 
435
 
 
436
    def test_unrelated(self):
 
437
        new_tree = self.make_branch_and_tree('new_tree')
 
438
 
 
439
        new_tree.commit('Commit one', rev_id='new_r1')
 
440
        new_tree.commit('Commit two', rev_id='new_r2')
 
441
        new_tree.commit('Commit three', rev_id='new_r3')
 
442
 
 
443
        self.assertInHistoryIs(None, 'new_r3', 'branch:new_tree')
 
444
 
 
445
        # XXX: Right now, we use fetch() to make sure the remote revisions
 
446
        # have been pulled into the local branch. We may change that
 
447
        # behavior in the future.
 
448
        self.failUnless(self.tree.branch.repository.has_revision('new_r3'))
 
449
 
 
450
    def test_no_commits(self):
 
451
        new_tree = self.make_branch_and_tree('new_tree')
 
452
        self.assertRaises(errors.NoCommits,
 
453
                          self.get_in_history, 'branch:new_tree')