~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: 2006-08-17 07:52:09 UTC
  • mfrom: (1910.3.4 trivial)
  • Revision ID: pqm@pqm.ubuntu.com-20060817075209-e85a1f9e05ff8b87
(andrew) Trivial fixes to NotImplemented errors.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006 by 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
18
17
import os
19
18
import time
20
19
 
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, 'null:', '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, 'null:', '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')
 
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
 
26
 
 
27
 
 
28
class TestRevisionNamespaces(TestCaseWithTransport):
220
29
 
221
30
    def test_revno_n_path(self):
222
 
        """Old revno:N:path tests"""
 
31
        """Test revision specifiers.
 
32
 
 
33
        These identify revisions by date, etc."""
223
34
        wta = self.make_branch_and_tree('a')
224
35
        ba = wta.branch
225
36
        
234
45
        wtb.commit('Commit two', rev_id='b@r-0-2')
235
46
        wtb.commit('Commit three', rev_id='b@r-0-3')
236
47
 
237
 
 
238
 
        self.assertEqual((1, 'a@r-0-1'),
239
 
                         spec_in_history('revno:1:a/', ba))
 
48
        self.assertEquals(RevisionSpec('revno:1:a/').in_history(ba),
 
49
                          (1, 'a@r-0-1'))
240
50
        # The argument of in_history should be ignored since it is
241
51
        # 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, 'null:', '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, 'null:', '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, 'null:', '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:')
 
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