/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_revisionnamespaces.py

  • Committer: John Arbash Meinel
  • Date: 2006-04-25 15:05:42 UTC
  • mfrom: (1185.85.85 bzr-encoding)
  • mto: This revision was merged to the branch mainline in revision 1752.
  • Revision ID: john@arbash-meinel.com-20060425150542-c7b518dca9928691
[merge] the old bzr-encoding changes, reparenting them on bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2012, 2016 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
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
import datetime
 
17
import os
18
18
import time
19
19
 
20
 
from breezy import (
21
 
    errors,
22
 
    revision as _mod_revision,
23
 
    )
24
 
from breezy.tests import TestCaseWithTransport
25
 
from breezy.revisionspec import (
26
 
    RevisionInfo,
27
 
    RevisionSpec,
28
 
    RevisionSpec_dwim,
29
 
    RevisionSpec_tag,
30
 
    )
31
 
 
32
 
 
33
 
def spec_in_history(spec, branch):
34
 
    """A simple helper to change a revision spec into a branch search"""
35
 
    return RevisionSpec.from_string(spec).in_history(branch)
36
 
 
37
 
 
38
 
# Basic class, which just creates a really basic set of revisions
39
 
class TestRevisionSpec(TestCaseWithTransport):
40
 
 
41
 
    def setUp(self):
42
 
        super(TestRevisionSpec, self).setUp()
43
 
        # this sets up a revision graph:
44
 
        # r1: []             1
45
 
        # alt_r2: [r1]       1.1.1
46
 
        # r2: [r1, alt_r2]   2
47
 
 
48
 
        self.tree = self.make_branch_and_tree('tree')
49
 
        self.build_tree(['tree/a'])
50
 
        self.tree.lock_write()
51
 
        self.addCleanup(self.tree.unlock)
52
 
        self.tree.add(['a'])
53
 
        self.tree.commit('a', rev_id=b'r1')
54
 
 
55
 
        self.tree2 = self.tree.controldir.sprout('tree2').open_workingtree()
56
 
        self.tree2.commit('alt', rev_id=b'alt_r2')
57
 
 
58
 
        self.tree.merge_from_branch(self.tree2.branch)
59
 
        self.tree.commit('second', rev_id=b'r2')
60
 
 
61
 
    def get_in_history(self, revision_spec):
62
 
        return spec_in_history(revision_spec, self.tree.branch)
63
 
 
64
 
    def assertInHistoryIs(self, exp_revno, exp_revision_id, revision_spec):
65
 
        rev_info = self.get_in_history(revision_spec)
66
 
        self.assertEqual(exp_revno, rev_info.revno,
67
 
                         'Revision spec: %r returned wrong revno: %r != %r'
68
 
                         % (revision_spec, exp_revno, rev_info.revno))
69
 
        self.assertEqual(exp_revision_id, rev_info.rev_id,
70
 
                         'Revision spec: %r returned wrong revision id:'
71
 
                         ' %r != %r'
72
 
                         % (revision_spec, exp_revision_id, rev_info.rev_id))
73
 
 
74
 
    def assertInvalid(self, revision_spec, extra='',
75
 
                      invalid_as_revision_id=True):
76
 
        try:
77
 
            self.get_in_history(revision_spec)
78
 
        except errors.InvalidRevisionSpec as e:
79
 
            self.assertEqual(revision_spec, e.spec)
80
 
            self.assertEqual(extra, e.extra)
81
 
        else:
82
 
            self.fail('Expected InvalidRevisionSpec to be raised for'
83
 
                      ' %r.in_history' % (revision_spec,))
84
 
        if invalid_as_revision_id:
85
 
            try:
86
 
                spec = RevisionSpec.from_string(revision_spec)
87
 
                spec.as_revision_id(self.tree.branch)
88
 
            except errors.InvalidRevisionSpec as e:
89
 
                self.assertEqual(revision_spec, e.spec)
90
 
                self.assertEqual(extra, e.extra)
91
 
            else:
92
 
                self.fail('Expected InvalidRevisionSpec to be raised for'
93
 
                          ' %r.as_revision_id' % (revision_spec,))
94
 
 
95
 
    def assertAsRevisionId(self, revision_id, revision_spec):
96
 
        """Calling as_revision_id() should return the specified id."""
97
 
        spec = RevisionSpec.from_string(revision_spec)
98
 
        self.assertEqual(revision_id,
99
 
                         spec.as_revision_id(self.tree.branch))
100
 
 
101
 
    def get_as_tree(self, revision_spec, tree=None):
102
 
        if tree is None:
103
 
            tree = self.tree
104
 
        spec = RevisionSpec.from_string(revision_spec)
105
 
        return spec.as_tree(tree.branch)
106
 
 
107
 
 
108
 
class RevisionSpecMatchOnTrap(RevisionSpec):
109
 
 
110
 
    def _match_on(self, branch, revs):
111
 
        self.last_call = (branch, revs)
112
 
        return super(RevisionSpecMatchOnTrap, self)._match_on(branch, revs)
113
 
 
114
 
 
115
 
class TestRevisionSpecBase(TestRevisionSpec):
116
 
 
117
 
    def test_wants_no_revision_history(self):
118
 
        # If wants_revision_history = False, then _match_on should get None for
119
 
        # the branch revision history
120
 
        spec = RevisionSpecMatchOnTrap('foo', _internal=True)
121
 
        spec.in_history(self.tree.branch)
122
 
 
123
 
        self.assertEqual((self.tree.branch, None), spec.last_call)
124
 
 
125
 
 
126
 
class TestOddRevisionSpec(TestRevisionSpec):
127
 
    """Test things that aren't normally thought of as revision specs"""
128
 
 
129
 
    def test_none(self):
130
 
        self.assertInHistoryIs(None, None, None)
131
 
 
132
 
    def test_object(self):
133
 
        self.assertRaises(TypeError, RevisionSpec.from_string, object())
134
 
 
135
 
 
136
 
class RevisionSpec_bork(RevisionSpec):
137
 
 
138
 
    prefix = 'irrelevant:'
139
 
 
140
 
    def _match_on(self, branch, revs):
141
 
        if self.spec == "bork":
142
 
            return RevisionInfo.from_revision_id(branch, b"r1")
143
 
        else:
144
 
            raise errors.InvalidRevisionSpec(self.spec, branch)
145
 
 
146
 
 
147
 
class TestRevisionSpec_dwim(TestRevisionSpec):
148
 
 
149
 
    # Don't need to test revno's explicitly since TRS_revno already
150
 
    # covers that well for us
151
 
    def test_dwim_spec_revno(self):
152
 
        self.assertInHistoryIs(2, b'r2', '2')
153
 
        self.assertAsRevisionId(b'alt_r2', '1.1.1')
154
 
 
155
 
    def test_dwim_spec_revid(self):
156
 
        self.assertInHistoryIs(2, b'r2', 'r2')
157
 
 
158
 
    def test_dwim_spec_tag(self):
159
 
        self.tree.branch.tags.set_tag('footag', b'r1')
160
 
        self.assertAsRevisionId(b'r1', 'footag')
161
 
        self.tree.branch.tags.delete_tag('footag')
162
 
        self.assertRaises(errors.InvalidRevisionSpec,
163
 
                          self.get_in_history, 'footag')
164
 
 
165
 
    def test_dwim_spec_tag_that_looks_like_revno(self):
166
 
        # Test that we slip past revno with things that look like revnos,
167
 
        # but aren't.  Tags are convenient for testing this since we can
168
 
        # make them look however we want.
169
 
        self.tree.branch.tags.set_tag('3', b'r2')
170
 
        self.assertAsRevisionId(b'r2', '3')
171
 
        self.build_tree(['tree/b'])
172
 
        self.tree.add(['b'])
173
 
        self.tree.commit('b', rev_id=b'r3')
174
 
        self.assertAsRevisionId(b'r3', '3')
175
 
 
176
 
    def test_dwim_spec_date(self):
177
 
        self.assertAsRevisionId(b'r1', 'today')
178
 
 
179
 
    def test_dwim_spec_branch(self):
180
 
        self.assertInHistoryIs(None, b'alt_r2', 'tree2')
181
 
 
182
 
    def test_dwim_spec_nonexistent(self):
183
 
        self.assertInvalid('somethingrandom', invalid_as_revision_id=False)
184
 
        self.assertInvalid('-1.1', invalid_as_revision_id=False)
185
 
        self.assertInvalid('.1', invalid_as_revision_id=False)
186
 
        self.assertInvalid('1..1', invalid_as_revision_id=False)
187
 
        self.assertInvalid('1.2..1', invalid_as_revision_id=False)
188
 
        self.assertInvalid('1.', invalid_as_revision_id=False)
189
 
 
190
 
    def test_append_dwim_revspec(self):
191
 
        original_dwim_revspecs = list(RevisionSpec_dwim._possible_revspecs)
192
 
 
193
 
        def reset_dwim_revspecs():
194
 
            RevisionSpec_dwim._possible_revspecs = original_dwim_revspecs
195
 
        self.addCleanup(reset_dwim_revspecs)
196
 
        RevisionSpec_dwim.append_possible_revspec(RevisionSpec_bork)
197
 
        self.assertAsRevisionId(b'r1', 'bork')
198
 
 
199
 
    def test_append_lazy_dwim_revspec(self):
200
 
        original_dwim_revspecs = list(RevisionSpec_dwim._possible_revspecs)
201
 
 
202
 
        def reset_dwim_revspecs():
203
 
            RevisionSpec_dwim._possible_revspecs = original_dwim_revspecs
204
 
        self.addCleanup(reset_dwim_revspecs)
205
 
        RevisionSpec_dwim.append_possible_lazy_revspec(
206
 
            "breezy.tests.test_revisionspec", "RevisionSpec_bork")
207
 
        self.assertAsRevisionId(b'r1', 'bork')
208
 
 
209
 
 
210
 
class TestRevisionSpec_revno(TestRevisionSpec):
211
 
 
212
 
    def test_positive_int(self):
213
 
        self.assertInHistoryIs(0, b'null:', '0')
214
 
        self.assertInHistoryIs(1, b'r1', '1')
215
 
        self.assertInHistoryIs(2, b'r2', '2')
216
 
        self.assertInvalid('3')
217
 
 
218
 
    def test_dotted_decimal(self):
219
 
        self.assertInHistoryIs(None, b'alt_r2', '1.1.1')
220
 
        self.assertInvalid('1.1.123')
221
 
 
222
 
    def test_negative_int(self):
223
 
        self.assertInHistoryIs(2, b'r2', '-1')
224
 
        self.assertInHistoryIs(1, b'r1', '-2')
225
 
 
226
 
        self.assertInHistoryIs(1, b'r1', '-3')
227
 
        self.assertInHistoryIs(1, b'r1', '-4')
228
 
        self.assertInHistoryIs(1, b'r1', '-100')
229
 
 
230
 
    def test_positive(self):
231
 
        self.assertInHistoryIs(0, b'null:', 'revno:0')
232
 
        self.assertInHistoryIs(1, b'r1', 'revno:1')
233
 
        self.assertInHistoryIs(2, b'r2', 'revno:2')
234
 
 
235
 
        self.assertInvalid('revno:3')
236
 
 
237
 
    def test_negative(self):
238
 
        self.assertInHistoryIs(2, b'r2', 'revno:-1')
239
 
        self.assertInHistoryIs(1, b'r1', 'revno:-2')
240
 
 
241
 
        self.assertInHistoryIs(1, b'r1', 'revno:-3')
242
 
        self.assertInHistoryIs(1, b'r1', 'revno:-4')
243
 
 
244
 
    def test_invalid_number(self):
245
 
        # Get the right exception text
246
 
        try:
247
 
            int('X')
248
 
        except ValueError as e:
249
 
            self.assertInvalid('revno:X', extra='\n' + str(e))
250
 
        else:
251
 
            self.fail()
252
 
 
253
 
    def test_missing_number_and_branch(self):
254
 
        self.assertInvalid('revno::',
255
 
                           extra='\ncannot have an empty revno and no branch')
256
 
 
257
 
    def test_invalid_number_with_branch(self):
258
 
        try:
259
 
            int('X')
260
 
        except ValueError as e:
261
 
            self.assertInvalid('revno:X:tree2', extra='\n' + str(e))
262
 
        else:
263
 
            self.fail()
264
 
 
265
 
    def test_non_exact_branch(self):
266
 
        # It seems better to require an exact path to the branch
267
 
        # Branch.open() rather than using Branch.open_containing()
268
 
        spec = RevisionSpec.from_string('revno:2:tree2/a')
269
 
        self.assertRaises(errors.NotBranchError,
270
 
                          spec.in_history, self.tree.branch)
271
 
 
272
 
    def test_with_branch(self):
273
 
        # Passing a URL overrides the supplied branch path
274
 
        revinfo = self.get_in_history('revno:2:tree2')
275
 
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
276
 
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
277
 
        self.assertEqual(2, revinfo.revno)
278
 
        self.assertEqual(b'alt_r2', revinfo.rev_id)
279
 
 
280
 
    def test_int_with_branch(self):
281
 
        revinfo = self.get_in_history('2:tree2')
282
 
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
283
 
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
284
 
        self.assertEqual(2, revinfo.revno)
285
 
        self.assertEqual(b'alt_r2', revinfo.rev_id)
286
 
 
287
 
    def test_with_url(self):
288
 
        url = self.get_url() + '/tree2'
289
 
        revinfo = self.get_in_history('revno:2:%s' % (url,))
290
 
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
291
 
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
292
 
        self.assertEqual(2, revinfo.revno)
293
 
        self.assertEqual(b'alt_r2', revinfo.rev_id)
294
 
 
295
 
    def test_negative_with_url(self):
296
 
        url = self.get_url() + '/tree2'
297
 
        revinfo = self.get_in_history('revno:-1:%s' % (url,))
298
 
        self.assertNotEqual(self.tree.branch.base, revinfo.branch.base)
299
 
        self.assertEqual(self.tree2.branch.base, revinfo.branch.base)
300
 
        self.assertEqual(2, revinfo.revno)
301
 
        self.assertEqual(b'alt_r2', revinfo.rev_id)
302
 
 
303
 
    def test_different_history_lengths(self):
304
 
        # Make sure we use the revisions and offsets in the supplied branch
305
 
        # not the ones in the original branch.
306
 
        self.tree2.commit('three', rev_id=b'r3')
307
 
        self.assertInHistoryIs(3, b'r3', 'revno:3:tree2')
308
 
        self.assertInHistoryIs(3, b'r3', 'revno:-1:tree2')
309
 
 
310
 
    def test_invalid_branch(self):
311
 
        self.assertRaises(errors.NotBranchError,
312
 
                          self.get_in_history, 'revno:-1:tree3')
313
 
 
314
 
    def test_invalid_revno_in_branch(self):
315
 
        self.tree.commit('three', rev_id=b'r3')
316
 
        self.assertInvalid('revno:3:tree2')
317
 
 
318
 
    def test_revno_n_path(self):
319
 
        """Old revno:N:path tests"""
320
 
        wta = self.make_branch_and_tree('a')
321
 
        ba = wta.branch
322
 
 
323
 
        wta.commit('Commit one', rev_id=b'a@r-0-1')
324
 
        wta.commit('Commit two', rev_id=b'a@r-0-2')
325
 
        wta.commit('Commit three', rev_id=b'a@r-0-3')
326
 
 
327
 
        wtb = self.make_branch_and_tree('b')
328
 
        bb = wtb.branch
329
 
 
330
 
        wtb.commit('Commit one', rev_id=b'b@r-0-1')
331
 
        wtb.commit('Commit two', rev_id=b'b@r-0-2')
332
 
        wtb.commit('Commit three', rev_id=b'b@r-0-3')
333
 
 
334
 
        self.assertEqual((1, b'a@r-0-1'),
335
 
                         spec_in_history('revno:1:a/', ba))
336
 
        # The argument of in_history should be ignored since it is
337
 
        # redundant with the path in the spec.
338
 
        self.assertEqual((1, b'a@r-0-1'),
339
 
                         spec_in_history('revno:1:a/', None))
340
 
        self.assertEqual((1, b'a@r-0-1'),
341
 
                         spec_in_history('revno:1:a/', bb))
342
 
        self.assertEqual((2, b'b@r-0-2'),
343
 
                         spec_in_history('revno:2:b/', None))
344
 
 
345
 
    def test_as_revision_id(self):
346
 
        self.assertAsRevisionId(b'null:', '0')
347
 
        self.assertAsRevisionId(b'r1', '1')
348
 
        self.assertAsRevisionId(b'r2', '2')
349
 
        self.assertAsRevisionId(b'r1', '-2')
350
 
        self.assertAsRevisionId(b'r2', '-1')
351
 
        self.assertAsRevisionId(b'alt_r2', '1.1.1')
352
 
 
353
 
    def test_as_tree(self):
354
 
        tree = self.get_as_tree('0')
355
 
        self.assertEqual(_mod_revision.NULL_REVISION, tree.get_revision_id())
356
 
        tree = self.get_as_tree('1')
357
 
        self.assertEqual(b'r1', tree.get_revision_id())
358
 
        tree = self.get_as_tree('2')
359
 
        self.assertEqual(b'r2', tree.get_revision_id())
360
 
        tree = self.get_as_tree('-2')
361
 
        self.assertEqual(b'r1', tree.get_revision_id())
362
 
        tree = self.get_as_tree('-1')
363
 
        self.assertEqual(b'r2', tree.get_revision_id())
364
 
        tree = self.get_as_tree('1.1.1')
365
 
        self.assertEqual(b'alt_r2', tree.get_revision_id())
366
 
 
367
 
 
368
 
class TestRevisionSpec_revid(TestRevisionSpec):
369
 
 
370
 
    def test_in_history(self):
371
 
        # We should be able to access revisions that are directly
372
 
        # in the history.
373
 
        self.assertInHistoryIs(1, b'r1', 'revid:r1')
374
 
        self.assertInHistoryIs(2, b'r2', 'revid:r2')
375
 
 
376
 
    def test_missing(self):
377
 
        self.assertInvalid('revid:r3', invalid_as_revision_id=False)
378
 
 
379
 
    def test_merged(self):
380
 
        """We can reach revisions in the ancestry"""
381
 
        self.assertInHistoryIs(None, b'alt_r2', 'revid:alt_r2')
382
 
 
383
 
    def test_not_here(self):
384
 
        self.tree2.commit('alt third', rev_id=b'alt_r3')
385
 
        # It exists in tree2, but not in tree
386
 
        self.assertInvalid('revid:alt_r3', invalid_as_revision_id=False)
387
 
 
388
 
    def test_in_repository(self):
389
 
        """We can get any revision id in the repository"""
390
 
        # XXX: This may change in the future, but for now, it is true
391
 
        self.tree2.commit('alt third', rev_id=b'alt_r3')
392
 
        self.tree.branch.fetch(self.tree2.branch, b'alt_r3')
393
 
        self.assertInHistoryIs(None, b'alt_r3', 'revid:alt_r3')
394
 
 
395
 
    def test_unicode(self):
396
 
        """We correctly convert a unicode ui string to an encoded revid."""
397
 
        revision_id = u'\N{SNOWMAN}'.encode('utf-8')
398
 
        self.tree.commit('unicode', rev_id=revision_id)
399
 
        self.assertInHistoryIs(3, revision_id, u'revid:\N{SNOWMAN}')
400
 
        self.assertInHistoryIs(3, revision_id, 'revid:' +
401
 
                               revision_id.decode('utf-8'))
402
 
 
403
 
    def test_as_revision_id(self):
404
 
        self.assertAsRevisionId(b'r1', 'revid:r1')
405
 
        self.assertAsRevisionId(b'r2', 'revid:r2')
406
 
        self.assertAsRevisionId(b'alt_r2', 'revid:alt_r2')
407
 
 
408
 
 
409
 
class TestRevisionSpec_last(TestRevisionSpec):
410
 
 
411
 
    def test_positive(self):
412
 
        self.assertInHistoryIs(2, b'r2', 'last:1')
413
 
        self.assertInHistoryIs(1, b'r1', 'last:2')
414
 
        self.assertInHistoryIs(0, b'null:', 'last:3')
415
 
 
416
 
    def test_empty(self):
417
 
        self.assertInHistoryIs(2, b'r2', 'last:')
418
 
 
419
 
    def test_negative(self):
420
 
        self.assertInvalid('last:-1',
421
 
                           extra='\nyou must supply a positive value')
422
 
 
423
 
    def test_missing(self):
424
 
        self.assertInvalid('last:4')
425
 
 
426
 
    def test_no_history(self):
427
 
        tree = self.make_branch_and_tree('tree3')
428
 
 
429
 
        self.assertRaises(errors.NoCommits,
430
 
                          spec_in_history, 'last:', tree.branch)
431
 
 
432
 
    def test_not_a_number(self):
433
 
        last_e = None
434
 
        try:
435
 
            int('Y')
436
 
        except ValueError as e:
437
 
            last_e = e
438
 
        self.assertInvalid('last:Y', extra='\n' + str(last_e))
439
 
 
440
 
    def test_as_revision_id(self):
441
 
        self.assertAsRevisionId(b'r2', 'last:1')
442
 
        self.assertAsRevisionId(b'r1', 'last:2')
443
 
 
444
 
 
445
 
class TestRevisionSpec_before(TestRevisionSpec):
446
 
 
447
 
    def test_int(self):
448
 
        self.assertInHistoryIs(1, b'r1', 'before:2')
449
 
        self.assertInHistoryIs(1, b'r1', 'before:-1')
450
 
 
451
 
    def test_before_one(self):
452
 
        self.assertInHistoryIs(0, b'null:', 'before:1')
453
 
 
454
 
    def test_before_none(self):
455
 
        self.assertInvalid('before:0',
456
 
                           extra='\ncannot go before the null: revision')
457
 
 
458
 
    def test_revid(self):
459
 
        self.assertInHistoryIs(1, b'r1', 'before:revid:r2')
460
 
 
461
 
    def test_last(self):
462
 
        self.assertInHistoryIs(1, b'r1', 'before:last:1')
463
 
 
464
 
    def test_alt_revid(self):
465
 
        # This will grab the left-most ancestor for alternate histories
466
 
        self.assertInHistoryIs(1, b'r1', 'before:revid:alt_r2')
467
 
 
468
 
    def test_alt_no_parents(self):
469
 
        new_tree = self.make_branch_and_tree('new_tree')
470
 
        new_tree.commit('first', rev_id=b'new_r1')
471
 
        self.tree.branch.fetch(new_tree.branch, b'new_r1')
472
 
        self.assertInHistoryIs(0, b'null:', 'before:revid:new_r1')
473
 
 
474
 
    def test_as_revision_id(self):
475
 
        self.assertAsRevisionId(b'r1', 'before:revid:r2')
476
 
        self.assertAsRevisionId(b'r1', 'before:2')
477
 
        self.assertAsRevisionId(b'r1', 'before:1.1.1')
478
 
        self.assertAsRevisionId(b'r1', 'before:revid:alt_r2')
479
 
 
480
 
 
481
 
class TestRevisionSpec_tag(TestRevisionSpec):
482
 
 
483
 
    def make_branch_and_tree(self, relpath):
484
 
        # override format as the default one may not support tags
485
 
        return TestRevisionSpec.make_branch_and_tree(
486
 
            self, relpath, format='dirstate-tags')
487
 
 
488
 
    def test_from_string_tag(self):
489
 
        spec = RevisionSpec.from_string('tag:bzr-0.14')
490
 
        self.assertIsInstance(spec, RevisionSpec_tag)
491
 
        self.assertEqual(spec.spec, 'bzr-0.14')
492
 
 
493
 
    def test_lookup_tag(self):
494
 
        self.tree.branch.tags.set_tag('bzr-0.14', b'r1')
495
 
        self.assertInHistoryIs(1, b'r1', 'tag:bzr-0.14')
496
 
        self.tree.branch.tags.set_tag('null_rev', b'null:')
497
 
        self.assertInHistoryIs(0, b'null:', 'tag:null_rev')
498
 
 
499
 
    def test_failed_lookup(self):
500
 
        # tags that don't exist give a specific message: arguably we should
501
 
        # just give InvalidRevisionSpec but I think this is more helpful
502
 
        self.assertRaises(errors.NoSuchTag,
503
 
                          self.get_in_history,
504
 
                          'tag:some-random-tag')
505
 
 
506
 
    def test_as_revision_id(self):
507
 
        self.tree.branch.tags.set_tag('my-tag', b'r2')
508
 
        self.tree.branch.tags.set_tag('null_rev', b'null:')
509
 
        self.assertAsRevisionId(b'r2', 'tag:my-tag')
510
 
        self.assertAsRevisionId(b'null:', 'tag:null_rev')
511
 
        self.assertAsRevisionId(b'r1', 'before:tag:my-tag')
512
 
 
513
 
 
514
 
class TestRevisionSpec_date(TestRevisionSpec):
515
 
 
516
 
    def setUp(self):
517
 
        super(TestRevisionSpec, self).setUp()
518
 
 
519
 
        new_tree = self.make_branch_and_tree('new_tree')
520
 
        new_tree.commit('Commit one', rev_id=b'new_r1',
521
 
                        timestamp=time.time() - 60 * 60 * 24)
522
 
        new_tree.commit('Commit two', rev_id=b'new_r2')
523
 
        new_tree.commit('Commit three', rev_id=b'new_r3')
524
 
 
525
 
        self.tree = new_tree
526
 
 
527
 
    def test_tomorrow(self):
528
 
        self.assertInvalid('date:tomorrow')
529
 
 
530
 
    def test_today(self):
531
 
        self.assertInHistoryIs(2, b'new_r2', 'date:today')
532
 
        self.assertInHistoryIs(1, b'new_r1', 'before:date:today')
533
 
 
534
 
    def test_yesterday(self):
535
 
        self.assertInHistoryIs(1, b'new_r1', 'date:yesterday')
536
 
 
537
 
    def test_invalid(self):
538
 
        self.assertInvalid('date:foobar', extra='\ninvalid date')
539
 
        # You must have '-' between year/month/day
540
 
        self.assertInvalid('date:20040404', extra='\ninvalid date')
541
 
        # Need 2 digits for each date piece
542
 
        self.assertInvalid('date:2004-4-4', extra='\ninvalid date')
543
 
 
544
 
    def test_day(self):
545
 
        now = datetime.datetime.now()
546
 
        self.assertInHistoryIs(2, b'new_r2',
547
 
                               'date:%04d-%02d-%02d' % (now.year, now.month, now.day))
548
 
 
549
 
    def test_as_revision_id(self):
550
 
        self.assertAsRevisionId(b'new_r2', 'date:today')
551
 
 
552
 
 
553
 
class TestRevisionSpec_ancestor(TestRevisionSpec):
554
 
 
555
 
    def test_non_exact_branch(self):
556
 
        # It seems better to require an exact path to the branch
557
 
        # Branch.open() rather than using Branch.open_containing()
558
 
        self.assertRaises(errors.NotBranchError,
559
 
                          self.get_in_history, 'ancestor:tree2/a')
560
 
 
561
 
    def test_simple(self):
562
 
        # Common ancestor of trees is 'alt_r2'
563
 
        self.assertInHistoryIs(None, b'alt_r2', 'ancestor:tree2')
564
 
 
565
 
        # Going the other way, we get a valid revno
566
 
        tmp = self.tree
567
 
        self.tree = self.tree2
568
 
        self.tree2 = tmp
569
 
        self.assertInHistoryIs(2, b'alt_r2', 'ancestor:tree')
570
 
 
571
 
    def test_self(self):
572
 
        self.assertInHistoryIs(2, b'r2', 'ancestor:tree')
573
 
 
574
 
    def test_unrelated(self):
575
 
        new_tree = self.make_branch_and_tree('new_tree')
576
 
 
577
 
        new_tree.commit('Commit one', rev_id=b'new_r1')
578
 
        new_tree.commit('Commit two', rev_id=b'new_r2')
579
 
        new_tree.commit('Commit three', rev_id=b'new_r3')
580
 
 
581
 
        # With no common ancestor, we should raise another user error
582
 
        self.assertRaises(errors.NoCommonAncestor,
583
 
                          self.get_in_history, 'ancestor:new_tree')
584
 
 
585
 
    def test_no_commits(self):
586
 
        new_tree = self.make_branch_and_tree('new_tree')
587
 
        self.assertRaises(errors.NoCommits,
588
 
                          spec_in_history, 'ancestor:new_tree',
589
 
                                           self.tree.branch)
590
 
 
591
 
        self.assertRaises(errors.NoCommits,
592
 
                          spec_in_history, 'ancestor:tree',
593
 
                                           new_tree.branch)
594
 
 
595
 
    def test_as_revision_id(self):
596
 
        self.assertAsRevisionId(b'alt_r2', 'ancestor:tree2')
597
 
 
598
 
    def test_default(self):
599
 
        # We don't have a parent to default to
600
 
        self.assertRaises(errors.NotBranchError, self.get_in_history,
601
 
                          'ancestor:')
602
 
 
603
 
        # Create a branch with a parent to default to
604
 
        tree3 = self.tree.controldir.sprout('tree3').open_workingtree()
605
 
        tree3.commit('foo', rev_id=b'r3')
606
 
        self.tree = tree3
607
 
        self.assertInHistoryIs(2, b'r2', 'ancestor:')
608
 
 
609
 
 
610
 
class TestRevisionSpec_branch(TestRevisionSpec):
611
 
 
612
 
    def test_non_exact_branch(self):
613
 
        # It seems better to require an exact path to the branch
614
 
        # Branch.open() rather than using Branch.open_containing()
615
 
        self.assertRaises(errors.NotBranchError,
616
 
                          self.get_in_history, 'branch:tree2/a')
617
 
 
618
 
    def test_simple(self):
619
 
        self.assertInHistoryIs(None, b'alt_r2', 'branch:tree2')
620
 
 
621
 
    def test_self(self):
622
 
        self.assertInHistoryIs(2, b'r2', 'branch:tree')
623
 
 
624
 
    def test_unrelated(self):
625
 
        new_tree = self.make_branch_and_tree('new_tree')
626
 
 
627
 
        new_tree.commit('Commit one', rev_id=b'new_r1')
628
 
        new_tree.commit('Commit two', rev_id=b'new_r2')
629
 
        new_tree.commit('Commit three', rev_id=b'new_r3')
630
 
 
631
 
        self.assertInHistoryIs(None, b'new_r3', 'branch:new_tree')
632
 
 
633
 
        # XXX: Right now, we use fetch() to make sure the remote revisions
634
 
        # have been pulled into the local branch. We may change that
635
 
        # behavior in the future.
636
 
        self.assertTrue(self.tree.branch.repository.has_revision(b'new_r3'))
637
 
 
638
 
    def test_no_commits(self):
639
 
        self.make_branch_and_tree('new_tree')
640
 
        self.assertRaises(errors.NoCommits,
641
 
                          self.get_in_history, 'branch:new_tree')
642
 
        self.assertRaises(errors.NoCommits,
643
 
                          self.get_as_tree, 'branch:new_tree')
644
 
 
645
 
    def test_as_revision_id(self):
646
 
        self.assertAsRevisionId(b'alt_r2', 'branch:tree2')
647
 
 
648
 
    def test_as_tree(self):
649
 
        tree = self.get_as_tree('branch:tree', self.tree2)
650
 
        self.assertEqual(b'r2', tree.get_revision_id())
651
 
        self.assertFalse(self.tree2.branch.repository.has_revision(b'r2'))
652
 
 
653
 
 
654
 
class TestRevisionSpec_submit(TestRevisionSpec):
655
 
 
656
 
    def test_submit_branch(self):
657
 
        # Common ancestor of trees is 'alt_r2'
658
 
        self.assertRaises(errors.NoSubmitBranch, self.get_in_history,
659
 
                          'submit:')
660
 
        self.tree.branch.set_parent('../tree2')
661
 
        self.assertInHistoryIs(None, b'alt_r2', 'submit:')
662
 
        self.tree.branch.set_parent('bogus')
663
 
        self.assertRaises(errors.NotBranchError, self.get_in_history,
664
 
                          'submit:')
665
 
        # submit branch overrides parent branch
666
 
        self.tree.branch.set_submit_branch('tree2')
667
 
        self.assertInHistoryIs(None, b'alt_r2', 'submit:')
668
 
 
669
 
    def test_as_revision_id(self):
670
 
        self.tree.branch.set_submit_branch('tree2')
671
 
        self.assertAsRevisionId(b'alt_r2', 'branch:tree2')
672
 
 
673
 
 
674
 
class TestRevisionSpec_mainline(TestRevisionSpec):
675
 
 
676
 
    def test_as_revision_id(self):
677
 
        self.assertAsRevisionId(b'r1', 'mainline:1')
678
 
        self.assertAsRevisionId(b'r2', 'mainline:1.1.1')
679
 
        self.assertAsRevisionId(b'r2', 'mainline:revid:alt_r2')
680
 
        spec = RevisionSpec.from_string('mainline:revid:alt_r22')
681
 
        e = self.assertRaises(errors.InvalidRevisionSpec,
682
 
                              spec.as_revision_id, self.tree.branch)
683
 
        self.assertContainsRe(str(e),
684
 
                              "Requested revision: 'mainline:revid:alt_r22' does not exist in"
685
 
                              " branch: ")
686
 
 
687
 
    def test_in_history(self):
688
 
        self.assertInHistoryIs(2, b'r2', 'mainline:revid:alt_r2')
689
 
 
690
 
 
691
 
class TestRevisionSpec_annotate(TestRevisionSpec):
692
 
 
693
 
    def setUp(self):
694
 
        super(TestRevisionSpec_annotate, self).setUp()
695
 
        self.tree = self.make_branch_and_tree('annotate-tree')
696
 
        self.build_tree_contents([('annotate-tree/file1', b'1\n')])
697
 
        self.tree.add('file1')
698
 
        self.tree.commit('r1', rev_id=b'r1')
699
 
        self.build_tree_contents([('annotate-tree/file1', b'2\n1\n')])
700
 
        self.tree.commit('r2', rev_id=b'r2')
701
 
        self.build_tree_contents([('annotate-tree/file1', b'2\n1\n3\n')])
702
 
 
703
 
    def test_as_revision_id_r1(self):
704
 
        self.assertAsRevisionId(b'r1', 'annotate:annotate-tree/file1:2')
705
 
 
706
 
    def test_as_revision_id_r2(self):
707
 
        self.assertAsRevisionId(b'r2', 'annotate:annotate-tree/file1:1')
708
 
 
709
 
    def test_as_revision_id_uncommitted(self):
710
 
        spec = RevisionSpec.from_string('annotate:annotate-tree/file1:3')
711
 
        e = self.assertRaises(errors.InvalidRevisionSpec,
712
 
                              spec.as_revision_id, self.tree.branch)
713
 
        self.assertContainsRe(str(e),
714
 
                              r"Requested revision: \'annotate:annotate-tree/file1:3\' does not"
715
 
                              " exist in branch: .*\nLine 3 has not been committed.")
716
 
 
717
 
    def test_non_existent_line(self):
718
 
        spec = RevisionSpec.from_string('annotate:annotate-tree/file1:4')
719
 
        e = self.assertRaises(errors.InvalidRevisionSpec,
720
 
                              spec.as_revision_id, self.tree.branch)
721
 
        self.assertContainsRe(str(e),
722
 
                              r"Requested revision: \'annotate:annotate-tree/file1:4\' does not"
723
 
                              " exist in branch: .*\nNo such line: 4")
724
 
 
725
 
    def test_invalid_line(self):
726
 
        spec = RevisionSpec.from_string('annotate:annotate-tree/file1:q')
727
 
        e = self.assertRaises(errors.InvalidRevisionSpec,
728
 
                              spec.as_revision_id, self.tree.branch)
729
 
        self.assertContainsRe(str(e),
730
 
                              r"Requested revision: \'annotate:annotate-tree/file1:q\' does not"
731
 
                              " exist in branch: .*\nNo such line: q")
732
 
 
733
 
    def test_no_such_file(self):
734
 
        spec = RevisionSpec.from_string('annotate:annotate-tree/file2:1')
735
 
        e = self.assertRaises(errors.InvalidRevisionSpec,
736
 
                              spec.as_revision_id, self.tree.branch)
737
 
        self.assertContainsRe(str(e),
738
 
                              r"Requested revision: \'annotate:annotate-tree/file2:1\' does not"
739
 
                              " exist in branch: .*\nFile 'file2' is not versioned")
740
 
 
741
 
    def test_no_such_file_with_colon(self):
742
 
        spec = RevisionSpec.from_string('annotate:annotate-tree/fi:le2:1')
743
 
        e = self.assertRaises(errors.InvalidRevisionSpec,
744
 
                              spec.as_revision_id, self.tree.branch)
745
 
        self.assertContainsRe(str(e),
746
 
                              r"Requested revision: \'annotate:annotate-tree/fi:le2:1\' does not"
747
 
                              " exist in branch: .*\nFile 'fi:le2' is not versioned")
 
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