~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_tags.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-10-05 21:15:13 UTC
  • mfrom: (5448.3.5 374700-Add-gnu-lsh-support)
  • Revision ID: pqm@pqm.ubuntu.com-20101005211513-whouyj5t7oo92gmq
(gz) Add support for GNU lsh as a secure shell client (Matthew Gordon)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2011, 2016 Canonical Ltd
 
1
# Copyright (C) 2007-2010 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
17
17
"""Tests for commands related to tags"""
18
18
 
19
19
from bzrlib import (
20
 
    errors,
 
20
    bzrdir,
21
21
    tag,
22
 
    transform,
23
22
    )
24
23
from bzrlib.branch import (
25
24
    Branch,
26
25
    )
27
 
from bzrlib.tests import (
28
 
    script,
29
 
    TestCaseWithTransport,
 
26
from bzrlib.bzrdir import BzrDir
 
27
from bzrlib.tests import TestCaseWithTransport
 
28
from bzrlib.repository import (
 
29
    Repository,
30
30
    )
31
 
from bzrlib.tests.matchers import ContainsNoVfsCalls
32
31
from bzrlib.workingtree import WorkingTree
33
32
 
34
33
 
35
34
class TestTagging(TestCaseWithTransport):
36
35
 
 
36
    # as of 0.14, the default format doesn't do tags so we need to use a
 
37
    # specific format
 
38
 
 
39
    def make_branch_and_tree(self, relpath):
 
40
        format = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
 
41
        return TestCaseWithTransport.make_branch_and_tree(self, relpath,
 
42
            format=format)
 
43
 
37
44
    def test_tag_command_help(self):
38
45
        out, err = self.run_bzr('help tag')
39
46
        self.assertContainsRe(out, 'Create, remove or modify a tag')
53
60
        Branch.hooks.install_named_hook('automatic_tag_name',
54
61
            get_tag_name, 'get tag name')
55
62
        out, err = self.run_bzr('tag -d branch')
56
 
        self.assertContainsRe(err, 'Created tag mytag.')
 
63
        self.assertContainsRe(out, 'Created tag mytag.')
57
64
 
58
65
    def test_tag_current_rev(self):
59
66
        t = self.make_branch_and_tree('branch')
61
68
            rev_id='first-revid')
62
69
        # make a tag through the command line
63
70
        out, err = self.run_bzr('tag -d branch NEWTAG')
64
 
        self.assertContainsRe(err, 'Created tag NEWTAG.')
 
71
        self.assertContainsRe(out, 'Created tag NEWTAG.')
65
72
        # tag should be observable through the api
66
 
        self.assertEqual(t.branch.tags.get_tag_dict(),
 
73
        self.assertEquals(t.branch.tags.get_tag_dict(),
67
74
                dict(NEWTAG='first-revid'))
68
75
        # can also create tags using -r
69
76
        self.run_bzr('tag -d branch tag2 -r1')
70
 
        self.assertEqual(t.branch.tags.lookup_tag('tag2'), 'first-revid')
 
77
        self.assertEquals(t.branch.tags.lookup_tag('tag2'), 'first-revid')
71
78
        # regression test: make sure a unicode revision from the user
72
79
        # gets turned into a str object properly. The use of a unicode
73
80
        # object for the revid is intentional.
74
81
        self.run_bzr(['tag', '-d', 'branch', 'tag3', u'-rrevid:first-revid'])
75
 
        self.assertEqual(t.branch.tags.lookup_tag('tag3'), 'first-revid')
 
82
        self.assertEquals(t.branch.tags.lookup_tag('tag3'), 'first-revid')
76
83
        # can also delete an existing tag
77
84
        out, err = self.run_bzr('tag --delete -d branch tag2')
78
85
        # cannot replace an existing tag normally
79
 
        out, err = self.run_bzr('tag -d branch NEWTAG -r0', retcode=3)
 
86
        out, err = self.run_bzr('tag -d branch NEWTAG', retcode=3)
80
87
        self.assertContainsRe(err, 'Tag NEWTAG already exists\\.')
81
88
        # ... but can if you use --force
82
 
        out, err = self.run_bzr('tag -d branch NEWTAG --force -r0')
83
 
        self.assertEqual("Updated tag NEWTAG.\n", err)
84
 
 
85
 
    def test_tag_same_revision(self):
86
 
        t = self.make_branch_and_tree('branch')
87
 
        t.commit(allow_pointless=True, message='initial commit',
88
 
            rev_id='first-revid')
89
 
        t.commit(allow_pointless=True, message='second commit',
90
 
            rev_id='second-revid')
91
 
        out, err = self.run_bzr('tag -rrevid:first-revid -d branch NEWTAG')
92
 
        out, err = self.run_bzr('tag -rrevid:first-revid -d branch NEWTAG')
93
 
        self.assertContainsRe(err,
94
 
            'Tag NEWTAG already exists for that revision\\.')
95
 
        out, err = self.run_bzr('tag -rrevid:second-revid -d branch NEWTAG',
96
 
            retcode=3)
97
 
        self.assertContainsRe(err, 'Tag NEWTAG already exists\\.')
 
89
        out, err = self.run_bzr('tag -d branch NEWTAG --force')
98
90
 
99
91
    def test_tag_delete_requires_name(self):
100
92
        out, err = self.run_bzr('tag -d branch', retcode=3)
109
101
        # branching copies the tag across
110
102
        self.run_bzr('branch branch1 branch2')
111
103
        b2 = Branch.open('branch2')
112
 
        self.assertEqual(b2.tags.lookup_tag('tag1'), 'first-revid')
 
104
        self.assertEquals(b2.tags.lookup_tag('tag1'), 'first-revid')
113
105
        # make a new tag and pull it
114
106
        b1.tags.set_tag('tag2', 'twa')
115
107
        self.run_bzr('pull -d branch2 branch1')
116
 
        self.assertEqual(b2.tags.lookup_tag('tag2'), 'twa')
 
108
        self.assertEquals(b2.tags.lookup_tag('tag2'), 'twa')
117
109
        # make a new tag and push it
118
110
        b1.tags.set_tag('tag3', 'san')
119
111
        self.run_bzr('push -d branch1 branch2')
120
 
        self.assertEqual(b2.tags.lookup_tag('tag3'), 'san')
 
112
        self.assertEquals(b2.tags.lookup_tag('tag3'), 'san')
121
113
        # make a new tag and merge it
122
114
        t.commit(allow_pointless=True, message='second commit',
123
115
            rev_id='second-revid')
125
117
        t2.commit(allow_pointless=True, message='commit in second')
126
118
        b1.tags.set_tag('tag4', 'second-revid')
127
119
        self.run_bzr('merge -d branch2 branch1')
128
 
        self.assertEqual(b2.tags.lookup_tag('tag4'), 'second-revid')
 
120
        self.assertEquals(b2.tags.lookup_tag('tag4'), 'second-revid')
129
121
        # pushing to a new location copies the tag across
130
122
        self.run_bzr('push -d branch1 branch3')
131
123
        b3 = Branch.open('branch3')
132
 
        self.assertEqual(b3.tags.lookup_tag('tag1'), 'first-revid')
133
 
 
134
 
    def make_master_and_checkout(self):
135
 
        builder = self.make_branch_builder('master')
136
 
        builder.build_commit(message='Initial commit.', rev_id='rev-1')
137
 
        master = builder.get_branch()
138
 
        child = master.create_checkout(self.get_url('child'))
139
 
        return master, child
140
 
 
141
 
    def make_fork(self, branch):
142
 
        fork = branch.create_clone_on_transport(self.get_transport('fork'))
143
 
        self.addCleanup(fork.lock_write().unlock)
144
 
        with transform.TransformPreview(fork.basis_tree()) as tt:
145
 
            tt.commit(fork, message='Commit in fork.', revision_id='fork-0')
146
 
        with transform.TransformPreview(fork.basis_tree()) as tt:
147
 
            tt.commit(fork, message='Commit in fork.', revision_id='fork-1')
148
 
        return fork
149
 
 
150
 
    def test_merge_without_commit_does_not_propagate_tags_to_master(self):
151
 
        """'bzr merge' alone does not propagate tags to a master branch.
152
 
 
153
 
        (If the user runs 'bzr commit', then that is when the tags from the
154
 
        merge are propagated.)
155
 
        """
156
 
        master, child = self.make_master_and_checkout()
157
 
        fork = self.make_fork(master)
158
 
        fork.tags.set_tag('new-tag', fork.last_revision())
159
 
        self.run_bzr(['merge', '../fork'], working_dir='child')
160
 
        self.assertEqual({}, master.tags.get_tag_dict())
161
 
 
162
 
    def test_commit_in_heavyweight_checkout_copies_tags_to_master(self):
163
 
        master, child = self.make_master_and_checkout()
164
 
        fork = self.make_fork(master)
165
 
        fork.tags.set_tag('new-tag', fork.last_revision())
166
 
        fork.tags.set_tag('non-ancestry-tag', 'fork-0')
167
 
        fork.tags.set_tag('absent-tag', 'absent-rev')
168
 
        script.run_script(self, """
169
 
            $ cd child
170
 
            $ bzr merge ../fork
171
 
            $ bzr commit -m "Merge fork."
172
 
            2>Committing to: .../master/
173
 
            2>Committed revision 2.
174
 
            """, null_output_matches_anything=True)
175
 
        # Merge copied the tag to child and commit propagated it to master
176
 
        expected_tag_dict = {
177
 
            'new-tag': fork.last_revision(),
178
 
            'non-ancestry-tag': 'fork-0',
179
 
            'absent-tag': 'absent-rev',
180
 
            }
181
 
        self.assertEqual(expected_tag_dict, child.branch.tags.get_tag_dict())
182
 
        self.assertEqual(expected_tag_dict, master.tags.get_tag_dict())
183
 
        # Revisions not in ancestry but named in tags are present
184
 
        child.branch.repository.get_revision('fork-0')
185
 
        master.repository.get_revision('fork-0')
186
 
 
187
 
    def test_commit_in_heavyweight_checkout_reports_tag_conflict(self):
188
 
        master, child = self.make_master_and_checkout()
189
 
        fork = self.make_fork(master)
190
 
        fork.tags.set_tag('new-tag', fork.last_revision())
191
 
        master_r1 = master.last_revision()
192
 
        master.tags.set_tag('new-tag', master_r1)
193
 
        script.run_script(self, """
194
 
            $ cd child
195
 
            $ bzr merge ../fork
196
 
            $ bzr commit -m "Merge fork."
197
 
            2>Committing to: .../master/
198
 
            2>Conflicting tags in bound branch:
199
 
            2>    new-tag
200
 
            2>Committed revision 2.
201
 
            """, null_output_matches_anything=True)
202
 
        # Merge copied the tag to child.  master's conflicting tag is unchanged.
203
 
        self.assertEqual(
204
 
            {'new-tag': fork.last_revision()}, child.branch.tags.get_tag_dict())
205
 
        self.assertEqual(
206
 
            {'new-tag': master_r1}, master.tags.get_tag_dict())
 
124
        self.assertEquals(b3.tags.lookup_tag('tag1'), 'first-revid')
207
125
 
208
126
    def test_list_tags(self):
209
127
        tree1 = self.make_branch_and_tree('branch1')
214
132
 
215
133
        b1 = tree1.branch
216
134
        # note how the tag for revid-1 sorts after the one for revid-2
217
 
        b1.tags.set_tag(u'tag1\u30d0', 'revid-2')
218
 
        b1.tags.set_tag(u'tag10\u30d0', 'missing') # not present in repository
219
 
        b1.tags.set_tag(u'tag2\u30d0', 'revid-1')
220
 
 
221
 
        # natural order
222
 
        out, err = self.run_bzr('tags -d branch1',
223
 
                                encoding='utf-8')
224
 
        self.assertEqual(err, '')
225
 
        self.assertContainsRe(out, (u'^tag1\u30d0  *2\ntag2\u30d0  *1\n' +
226
 
            u'tag10\u30d0 *\\?\n').encode('utf-8'))
 
135
        b1.tags.set_tag(u'tagA\u30d0', 'revid-2')
 
136
        b1.tags.set_tag(u'tagB\u30d0', 'missing') # not present in repository
 
137
        b1.tags.set_tag(u'tagC\u30d0', 'revid-1')
227
138
 
228
139
        # lexicographical order
229
 
        out, err = self.run_bzr('tags --sort=alpha -d branch1',
230
 
                                encoding='utf-8')
231
 
        self.assertEqual(err, '')
232
 
        self.assertContainsRe(out, (u'^tag10\u30d0  *\\?\ntag1\u30d0  *2\n' +
233
 
            u'tag2\u30d0 *1\n').encode('utf-8'))
 
140
        out, err = self.run_bzr('tags -d branch1', encoding='utf-8')
 
141
        self.assertEquals(err, '')
 
142
        self.assertContainsRe(out, (u'^tagA\u30d0  *2\ntagB\u30d0  *\\?\n' +
 
143
            u'tagC\u30d0 *1\n').encode('utf-8'))
234
144
 
235
 
        out, err = self.run_bzr('tags --sort=alpha --show-ids -d branch1',
236
 
                                encoding='utf-8')
237
 
        self.assertEqual(err, '')
238
 
        self.assertContainsRe(out, (u'^tag10\u30d0  *missing\n' +
239
 
            u'tag1\u30d0  *revid-2\ntag2\u30d0 *revid-1\n').encode('utf-8'))
 
145
        out, err = self.run_bzr('tags --show-ids -d branch1', encoding='utf-8')
 
146
        self.assertEquals(err, '')
 
147
        self.assertContainsRe(out, (u'^tagA\u30d0  *revid-2\n' +
 
148
            u'tagB\u30d0  *missing\ntagC\u30d0 *revid-1\n').encode('utf-8'))
240
149
 
241
150
        # chronological order
242
151
        out, err = self.run_bzr('tags --sort=time -d branch1',
243
152
                encoding='utf-8')
244
 
        self.assertEqual(err, '')
245
 
        self.assertContainsRe(out, (u'^tag2\u30d0  *1\ntag1\u30d0  *2\n' +
246
 
            u'tag10\u30d0 *\\?\n').encode('utf-8'))
 
153
        self.assertEquals(err, '')
 
154
        self.assertContainsRe(out, (u'^tagC\u30d0  *1\ntagA\u30d0  *2\n' +
 
155
            u'tagB\u30d0 *\\?\n').encode('utf-8'))
247
156
 
248
157
        out, err = self.run_bzr('tags --sort=time --show-ids -d branch1',
249
158
                encoding='utf-8')
250
 
        self.assertEqual(err, '')
251
 
        self.assertContainsRe(out, (u'^tag2\u30d0  *revid-1\n' +
252
 
            u'tag1\u30d0  *revid-2\ntag10\u30d0 *missing\n').encode('utf-8'))
 
159
        self.assertEquals(err, '')
 
160
        self.assertContainsRe(out, (u'^tagC\u30d0  *revid-1\n' +
 
161
            u'tagA\u30d0  *revid-2\ntagB\u30d0 *missing\n').encode('utf-8'))
253
162
 
254
163
        # now test dotted revnos
255
164
        tree2 = tree1.bzrdir.sprout('branch2').open_workingtree()
264
173
        tree1.commit('merge', rev_id='revid-4')
265
174
 
266
175
        out, err = self.run_bzr('tags -d branch1', encoding='utf-8')
267
 
        self.assertEqual(err, '')
 
176
        self.assertEquals(err, '')
268
177
        self.assertContainsRe(out, r'tagD  *2\.1\.1\n')
269
178
        out, err = self.run_bzr('tags -d branch2', encoding='utf-8')
270
 
        self.assertEqual(err, '')
 
179
        self.assertEquals(err, '')
271
180
        self.assertContainsRe(out, r'tagD  *3\n')
272
181
 
273
 
    def test_list_tags_dotted_revnos_unsupported(self):
274
 
        tree = self.make_branch_and_tree('branch')
275
 
        rev1 = tree.commit("rev1")
276
 
        tree.branch.tags.set_tag("mytag", rev1)
277
 
        def revision_id_to_dotted_revno(self, revid):
278
 
            raise errors.UnsupportedOperation(revision_id_to_dotted_revno, self)
279
 
        self.overrideAttr(Branch, "revision_id_to_dotted_revno",
280
 
            revision_id_to_dotted_revno)
281
 
        out, err = self.run_bzr('tags -d branch', encoding='utf-8')
282
 
        self.assertEqual(out, 'mytag                ?\n')
283
 
 
284
182
    def test_list_tags_revision_filtering(self):
285
183
        tree1 = self.make_branch_and_tree('.')
286
184
        tree1.commit(allow_pointless=True, message='revision 1',
312
210
            error_regexes=["bzr: ERROR: Requested revision: '123.123' "
313
211
                "does not exist in branch:"])
314
212
 
315
 
    def test_sort_tags_custom(self):
316
 
        def sort_by_dots(branch, tags):
317
 
            def sort_key((tag, revid)):
318
 
                return tag.count(".")
319
 
            tags.sort(key=sort_key)
320
 
 
321
 
        # Register a custom sort method
322
 
        tag.tag_sort_methods.register("dots", sort_by_dots, "Sort by dots.")
323
 
        self.addCleanup(tag.tag_sort_methods.remove, "dots")
324
 
 
325
 
        tree1 = self.make_branch_and_tree('branch1')
326
 
        tree1.commit(allow_pointless=True, message='revision 1',
327
 
                rev_id='revid-1', timestamp=10)
328
 
        tree1.commit(allow_pointless=True, message='revision 2',
329
 
                rev_id='revid-2', timestamp=15)
330
 
 
331
 
        b1 = tree1.branch
332
 
 
333
 
        b1.tags.set_tag(u'tag..', 'revid-2')
334
 
        b1.tags.set_tag(u'tag....', 'missing') # not present in repository
335
 
        b1.tags.set_tag(u'tag.', 'revid-1')
336
 
        b1.tags.set_tag(u'tag...', 'revid-1')
337
 
        b1.tags.set_tag(u'tag....', 'revid-1')
338
 
 
339
 
        # sorted by number of dots
340
 
        out, err = self.run_bzr('tags --sort=dots -d branch1')
341
 
        self.assertEqual(err, '')
342
 
        self.assertEqual([
343
 
            'tag.                 1',
344
 
            'tag..                2',
345
 
            'tag...               1',
346
 
            'tag....              1'],
347
 
            out.splitlines())
348
 
 
349
213
    def _check_tag_filter(self, argstr, expected_revnos):
350
214
        #upper bound of laziness
351
215
        out, err = self.run_bzr('tags ' + argstr)
352
 
        self.assertEqual(err, '')
 
216
        self.assertEquals(err, '')
353
217
        self.assertContainsRe(out, "^" + ''.join(["tag %s +%s\n" % (
354
218
            revno, revno) for revno in expected_revnos]) + "$")
355
219
 
367
231
        self.assertContainsRe(out,
368
232
                'Conflicting tags:\n.*' + tagname.encode('utf-8'))
369
233
        # pull should give a warning about the tags
370
 
        out, err = self.run_bzr('pull -d one two', encoding='utf-8',
371
 
            retcode=1)
 
234
        out, err = self.run_bzr('pull -d one two', encoding='utf-8')
372
235
        self.assertContainsRe(out,
373
236
                'Conflicting tags:\n.*' + tagname.encode('utf-8'))
374
237
        # merge should give a warning about the tags -- not implemented yet
375
238
        ## out, err = self.run_bzr('merge -d one two', encoding='utf-8')
376
239
        ## self.assertContainsRe(out,
377
240
        ##         'Conflicting tags:\n.*' + tagname.encode('utf-8'))
378
 
 
379
 
    def test_tag_quiet(self):
380
 
        t1 = self.make_branch_and_tree('')
381
 
        out, err = self.run_bzr('tag --quiet test1')
382
 
        self.assertEqual('', out)
383
 
        self.assertEqual('', err)
384
 
 
385
 
    def test_tag_delete_quiet(self):
386
 
        t1 = self.make_branch_and_tree('')
387
 
        self.run_bzr('tag test1')
388
 
        out, err = self.run_bzr('tag --delete --quiet test1')
389
 
        self.assertEqual('', out)
390
 
        self.assertEqual('', err)
391
 
 
392
 
    def test_tags_with_mainline_ghosts(self):
393
 
        tree = self.make_branch_and_tree('tree1')
394
 
        tree.set_parent_ids(["spooky"], allow_leftmost_as_ghost=True)
395
 
        tree.add('')
396
 
        tree.commit('msg1', rev_id='rev1')
397
 
        tree.commit('msg2', rev_id='rev2')
398
 
        tree.branch.tags.set_tag('unknown', 'out-of-mainline')
399
 
        tree.branch.tags.set_tag('ghost', 'spooky')
400
 
        tree.branch.tags.set_tag('tag1', 'rev1')
401
 
        tree.branch.tags.set_tag('tag2', 'rev2')
402
 
 
403
 
        out, err = self.run_bzr('tags -d tree1', encoding='utf-8')
404
 
        self.assertEqual(out,
405
 
            'ghost                ?\n'
406
 
            'tag1                 1\n'
407
 
            'tag2                 2\n'
408
 
            'unknown              ?\n')
409
 
        self.assertEqual('', err)
410
 
 
411
 
 
412
 
class TestSmartServerCat(TestCaseWithTransport):
413
 
 
414
 
    def test_set_tag(self):
415
 
        self.setup_smart_server_with_call_log()
416
 
        t = self.make_branch_and_tree('branch')
417
 
        self.build_tree_contents([('branch/foo', 'thecontents')])
418
 
        t.add("foo")
419
 
        t.commit("message")
420
 
        self.reset_smart_call_log()
421
 
        out, err = self.run_bzr(['tag', "-d", self.get_url('branch'), "tagname"])
422
 
        # This figure represent the amount of work to perform this use case. It
423
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
424
 
        # being too low. If rpc_count increases, more network roundtrips have
425
 
        # become necessary for this use case. Please do not adjust this number
426
 
        # upwards without agreement from bzr's network support maintainers.
427
 
        self.assertLength(9, self.hpss_calls)
428
 
        self.assertLength(1, self.hpss_connections)
429
 
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
430
 
 
431
 
    def test_show_tags(self):
432
 
        self.setup_smart_server_with_call_log()
433
 
        t = self.make_branch_and_tree('branch')
434
 
        self.build_tree_contents([('branch/foo', 'thecontents')])
435
 
        t.add("foo")
436
 
        t.commit("message")
437
 
        t.branch.tags.set_tag("sometag", "rev1")
438
 
        t.branch.tags.set_tag("sometag", "rev2")
439
 
        self.reset_smart_call_log()
440
 
        out, err = self.run_bzr(['tags', "-d", self.get_url('branch')])
441
 
        # This figure represent the amount of work to perform this use case. It
442
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
443
 
        # being too low. If rpc_count increases, more network roundtrips have
444
 
        # become necessary for this use case. Please do not adjust this number
445
 
        # upwards without agreement from bzr's network support maintainers.
446
 
        self.assertLength(6, self.hpss_calls)
447
 
        self.assertLength(1, self.hpss_connections)
448
 
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)