~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_revisionnamespaces.py

  • Committer: Robert Collins
  • Date: 2006-05-02 04:07:43 UTC
  • mto: (1692.4.1 integration)
  • mto: This revision was merged to the branch mainline in revision 1694.
  • Revision ID: robertc@robertcollins.net-20060502040743-c3eae60f1b9edf1c
Fix knit based push to only perform 2 appends to the target, rather that 2*new-versions.

Show diffs side-by-side

added added

removed removed

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