~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_revisionnamespaces.py

  • Committer: John Arbash Meinel
  • Date: 2007-08-14 19:29:56 UTC
  • mto: This revision was merged to the branch mainline in revision 2698.
  • Revision ID: john@arbash-meinel.com-20070814192956-34h336i5q3m34ods
Switch bzr.dev to 0.91 development

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