~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_revisionnamespaces.py

  • Committer: Robert Collins
  • Date: 2007-03-08 04:06:06 UTC
  • mfrom: (2323.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 2442.
  • Revision ID: robertc@robertcollins.net-20070308040606-84gsniv56huiyjt4
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

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