~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2007, 2009-2012, 2016 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
22
22
 
23
23
from bzrlib import (
24
24
    branch,
25
 
    bzrdir,
 
25
    controldir,
26
26
    errors,
27
 
    repository,
28
27
    tests,
29
28
    )
30
29
from bzrlib.tests import per_branch
41
40
            raise tests.TestSkipped(
42
41
                "format %s doesn't support tags" % branch._format)
43
42
 
 
43
    def make_branch_with_revisions(self, relpath, revisions):
 
44
        builder = self.make_branch_builder(relpath)
 
45
        builder.start_series()
 
46
        for revid in revisions:
 
47
            builder.build_commit(rev_id=revid)
 
48
        builder.finish_series()
 
49
        return builder.get_branch()
 
50
 
44
51
    def test_tags_initially_empty(self):
45
52
        b = self.make_branch('b')
46
53
        tags = b.tags.get_tag_dict()
47
54
        self.assertEqual(tags, {})
48
55
 
49
56
    def test_make_and_lookup_tag(self):
50
 
        b = self.make_branch('b')
 
57
        b = self.make_branch_with_revisions('b',
 
58
            ['target-revid-1', 'target-revid-2'])
51
59
        b.tags.set_tag('tag-name', 'target-revid-1')
52
60
        b.tags.set_tag('other-name', 'target-revid-2')
53
61
        # then reopen the branch and see they're still there
64
72
        self.assertFalse(b.tags.has_tag('imaginary'))
65
73
 
66
74
    def test_reverse_tag_dict(self):
67
 
        b = self.make_branch('b')
 
75
        b = self.make_branch_with_revisions('b',
 
76
            ['target-revid-1', 'target-revid-2'])
68
77
        b.tags.set_tag('tag-name', 'target-revid-1')
69
78
        b.tags.set_tag('other-name', 'target-revid-2')
70
79
        # then reopen the branch and check reverse map id->tags list
71
80
        b = branch.Branch.open('b')
72
 
        self.assertEqual(b.tags.get_reverse_tag_dict(),
 
81
        self.assertEqual(dict(b.tags.get_reverse_tag_dict()),
73
82
            {'target-revid-1': ['tag-name'],
74
83
             'target-revid-2': ['other-name'],
75
84
            })
76
85
 
 
86
    def test_ghost_tag(self):
 
87
        b = self.make_branch('b')
 
88
        if not b._format.supports_tags_referencing_ghosts():
 
89
            self.assertRaises(errors.GhostTagsNotSupported,
 
90
                b.tags.set_tag, "ghost", "idontexist")
 
91
        else:
 
92
            b.tags.set_tag("ghost", "idontexist")
 
93
            self.assertEqual("idontexist", b.tags.lookup_tag("ghost"))
 
94
 
77
95
    def test_no_such_tag(self):
78
96
        b = self.make_branch('b')
79
97
        try:
80
98
            b.tags.lookup_tag('bosko')
81
99
        except errors.NoSuchTag, e:
82
 
            self.assertEquals(e.tag_name, 'bosko')
83
 
            self.assertEquals(str(e), 'No such tag: bosko')
 
100
            self.assertEqual(e.tag_name, 'bosko')
 
101
            self.assertEqual(str(e), 'No such tag: bosko')
84
102
        else:
85
103
            self.fail("didn't get expected exception")
86
104
 
87
105
    def test_merge_tags(self):
88
 
        b1 = self.make_branch('b1')
89
 
        b2 = self.make_branch('b2')
 
106
        b1 = self.make_branch_with_revisions('b1', ['revid', 'revid-1'])
 
107
        b2 = self.make_branch_with_revisions('b2', ['revid', 'revid-2'])
90
108
        # if there are tags in the source and not the destination, then they
91
109
        # just go across
92
110
        b1.tags.set_tag('tagname', 'revid')
93
111
        b1.tags.merge_to(b2.tags)
94
 
        self.assertEquals(b2.tags.lookup_tag('tagname'), 'revid')
 
112
        self.assertEqual(b2.tags.lookup_tag('tagname'), 'revid')
95
113
        # if a tag is in the destination and not in the source, it is not
96
114
        # removed when we merge them
97
115
        b2.tags.set_tag('in-destination', 'revid')
98
 
        result = b1.tags.merge_to(b2.tags)
99
 
        self.assertEquals(list(result), [])
100
 
        self.assertEquals(b2.tags.lookup_tag('in-destination'), 'revid')
 
116
        updates, conflicts = b1.tags.merge_to(b2.tags)
 
117
        self.assertEqual(list(conflicts), [])
 
118
        self.assertEqual(updates, {})
 
119
        self.assertEqual(b2.tags.lookup_tag('in-destination'), 'revid')
101
120
        # if there's a conflicting tag, it's reported -- the command line
102
121
        # interface will say "these tags couldn't be copied"
103
122
        b1.tags.set_tag('conflicts', 'revid-1')
104
123
        b2.tags.set_tag('conflicts', 'revid-2')
105
 
        result = b1.tags.merge_to(b2.tags)
106
 
        self.assertEquals(list(result),
 
124
        updates, conflicts = b1.tags.merge_to(b2.tags)
 
125
        self.assertEqual(list(conflicts),
107
126
            [('conflicts', 'revid-1', 'revid-2')])
108
127
        # and it keeps the same value
109
 
        self.assertEquals(b2.tags.lookup_tag('conflicts'), 'revid-2')
 
128
        self.assertEqual(updates, {})
 
129
        self.assertEqual(b2.tags.lookup_tag('conflicts'), 'revid-2')
110
130
 
111
131
    def test_unicode_tag(self):
112
 
        b1 = self.make_branch('b')
113
132
        tag_name = u'\u3070'
114
133
        # in anticipation of the planned change to treating revision ids as
115
134
        # just 8bit strings
116
135
        revid = ('revid' + tag_name).encode('utf-8')
 
136
        b1 = self.make_branch_with_revisions('b', [revid])
117
137
        b1.tags.set_tag(tag_name, revid)
118
 
        self.assertEquals(b1.tags.lookup_tag(tag_name), revid)
 
138
        self.assertEqual(b1.tags.lookup_tag(tag_name), revid)
119
139
 
120
140
    def test_delete_tag(self):
121
 
        b = self.make_branch('b')
122
141
        tag_name = u'\N{GREEK SMALL LETTER ALPHA}'
123
142
        revid = ('revid' + tag_name).encode('utf-8')
 
143
        b = self.make_branch_with_revisions('b', [revid])
124
144
        b.tags.set_tag(tag_name, revid)
125
145
        # now try to delete it
126
146
        b.tags.delete_tag(tag_name)
128
148
        self.assertRaises(errors.NoSuchTag,
129
149
            b.tags.lookup_tag, tag_name)
130
150
        # and it's not in the dictionary
131
 
        self.assertEquals(b.tags.get_tag_dict(), {})
 
151
        self.assertEqual(b.tags.get_tag_dict(), {})
132
152
        # and you can't remove it a second time
133
153
        self.assertRaises(errors.NoSuchTag,
134
154
            b.tags.delete_tag, tag_name)
147
167
        # Open the same branch twice.  Read-lock one, and then mutate the tags
148
168
        # in the second.  The read-locked branch never re-reads the tags, so it
149
169
        # never observes the changed/new tags.
150
 
        b1 = self.make_branch('b')
 
170
        b1 = self.make_branch_with_revisions('b',
 
171
            ['rev-1', 'rev-1-changed', 'rev-2'])
151
172
        b1.tags.set_tag('one', 'rev-1')
152
 
        b2 = b1.bzrdir.open_branch()
 
173
        b2 = controldir.ControlDir.open('b').open_branch()
153
174
        b1.lock_read()
154
175
        self.assertEqual({'one': 'rev-1'}, b1.tags.get_tag_dict())
155
176
        # Add a tag and modify a tag in b2.  b1 is read-locked and has already
166
187
    def test_unlocked_does_not_cache_tags(self):
167
188
        """Unlocked branches do not cache tags."""
168
189
        # Open the same branch twice.
169
 
        b1 = self.make_branch('b')
 
190
        b1 = self.make_branch_with_revisions('b',
 
191
            ['rev-1', 'rev-1-changed', 'rev-2'])
170
192
        b1.tags.set_tag('one', 'rev-1')
171
193
        b2 = b1.bzrdir.open_branch()
172
194
        self.assertEqual({'one': 'rev-1'}, b1.tags.get_tag_dict())
182
204
        returns a copy of the cached data so that callers cannot accidentally
183
205
        corrupt the cache.
184
206
        """
185
 
        b = self.make_branch('b')
 
207
        b = self.make_branch_with_revisions('b',
 
208
            ['rev-1', 'rev-2', 'rev-3'])
186
209
        b.tags.set_tag('one', 'rev-1')
187
210
        self.addCleanup(b.lock_read().unlock)
188
211
        # The first time the data returned will not be in the cache
196
219
        self.assertEqual({'one': 'rev-1'}, b.tags.get_tag_dict())
197
220
 
198
221
    def make_write_locked_branch_with_one_tag(self):
199
 
        b = self.make_branch('b')
 
222
        b = self.make_branch_with_revisions('b',
 
223
            ['rev-1', 'rev-1-changed', 'rev-2'])
200
224
        b.tags.set_tag('one', 'rev-1')
201
225
        self.addCleanup(b.lock_write().unlock)
202
226
        # Populate the cache
215
239
 
216
240
    def test_merge_to_invalides_cache(self):
217
241
        b1 = self.make_write_locked_branch_with_one_tag()
218
 
        b2 = self.make_branch('b2')
 
242
        b2 = self.make_branch_with_revisions('b2', ['rev-2', 'rev-1'])
219
243
        b2.tags.set_tag('two', 'rev-2')
220
244
        b2.tags.merge_to(b1.tags)
221
245
        self.assertEqual(
266
290
        child.bind(master)
267
291
        child.update()
268
292
        other.tags.merge_to(child.tags)
269
 
        self.assertEquals('rev-1', child.tags.lookup_tag('foo'))
270
 
        self.assertEquals('rev-1', master.tags.lookup_tag('foo'))
 
293
        self.assertEqual('rev-1', child.tags.lookup_tag('foo'))
 
294
        self.assertEqual('rev-1', master.tags.lookup_tag('foo'))
271
295
 
272
296
    def test_ignore_master_disables_tag_propagation(self):
273
297
        """merge_to(child, ignore_master=True) does not merge tags to the
280
304
        child.bind(master)
281
305
        child.update()
282
306
        other.tags.merge_to(child.tags, ignore_master=True)
283
 
        self.assertEquals('rev-1', child.tags.lookup_tag('foo'))
 
307
        self.assertEqual('rev-1', child.tags.lookup_tag('foo'))
284
308
        self.assertRaises(errors.NoSuchTag, master.tags.lookup_tag, 'foo')
285
309
 
286
310
    def test_merge_to_overwrite_conflict_in_master(self):
294
318
        child.bind(master)
295
319
        child.update()
296
320
        master.tags.set_tag('foo', 'rev-2')
297
 
        tag_conflicts = other.tags.merge_to(child.tags, overwrite=True)
298
 
        self.assertEquals('rev-1', child.tags.lookup_tag('foo'))
299
 
        self.assertEquals('rev-1', master.tags.lookup_tag('foo'))
 
321
        tag_updates, tag_conflicts = other.tags.merge_to(child.tags, overwrite=True)
 
322
        self.assertEqual('rev-1', child.tags.lookup_tag('foo'))
 
323
        self.assertEqual('rev-1', master.tags.lookup_tag('foo'))
 
324
        self.assertEqual({"foo": "rev-1"}, tag_updates)
300
325
        self.assertLength(0, tag_conflicts)
301
326
 
302
327
    def test_merge_to_overwrite_conflict_in_child_and_master(self):
310
335
        child = self.make_branch('child')
311
336
        child.bind(master)
312
337
        child.update()
313
 
        tag_conflicts = other.tags.merge_to(child.tags, overwrite=True)
314
 
        self.assertEquals('rev-1', child.tags.lookup_tag('foo'))
315
 
        self.assertEquals('rev-1', master.tags.lookup_tag('foo'))
 
338
        tag_updates, tag_conflicts = other.tags.merge_to(
 
339
            child.tags, overwrite=True)
 
340
        self.assertEqual('rev-1', child.tags.lookup_tag('foo'))
 
341
        self.assertEqual('rev-1', master.tags.lookup_tag('foo'))
 
342
        self.assertEqual({u'foo': 'rev-1'}, tag_updates)
316
343
        self.assertLength(0, tag_conflicts)
317
344
 
318
345
    def test_merge_to_conflict_in_child_only(self):
327
354
        child.bind(master)
328
355
        child.update()
329
356
        master.tags.delete_tag('foo')
330
 
        tag_conflicts = other.tags.merge_to(child.tags)
 
357
        tag_updates, tag_conflicts = other.tags.merge_to(child.tags)
331
358
        # Conflict in child, so it is unchanged.
332
 
        self.assertEquals('rev-2', child.tags.lookup_tag('foo'))
 
359
        self.assertEqual('rev-2', child.tags.lookup_tag('foo'))
333
360
        # No conflict in the master, so the 'foo' tag equals other's value here.
334
 
        self.assertEquals('rev-1', master.tags.lookup_tag('foo'))
 
361
        self.assertEqual('rev-1', master.tags.lookup_tag('foo'))
335
362
        # The conflict is reported.
336
 
        self.assertEquals([(u'foo', 'rev-1', 'rev-2')], list(tag_conflicts))
 
363
        self.assertEqual([(u'foo', 'rev-1', 'rev-2')], list(tag_conflicts))
 
364
        self.assertEqual({u'foo': 'rev-1'}, tag_updates)
337
365
 
338
366
    def test_merge_to_conflict_in_master_only(self):
339
367
        """When new_tags.merge_to(child.tags) conflicts with the master but not
346
374
        child.bind(master)
347
375
        child.update()
348
376
        master.tags.set_tag('foo', 'rev-2')
349
 
        tag_conflicts = other.tags.merge_to(child.tags)
 
377
        tag_updates, tag_conflicts = other.tags.merge_to(child.tags)
350
378
        # No conflict in the child, so the 'foo' tag equals other's value here.
351
 
        self.assertEquals('rev-1', child.tags.lookup_tag('foo'))
 
379
        self.assertEqual('rev-1', child.tags.lookup_tag('foo'))
352
380
        # Conflict in master, so it is unchanged.
353
 
        self.assertEquals('rev-2', master.tags.lookup_tag('foo'))
 
381
        self.assertEqual('rev-2', master.tags.lookup_tag('foo'))
354
382
        # The conflict is reported.
355
 
        self.assertEquals([(u'foo', 'rev-1', 'rev-2')], list(tag_conflicts))
 
383
        self.assertEqual({u'foo': 'rev-1'}, tag_updates)
 
384
        self.assertEqual([(u'foo', 'rev-1', 'rev-2')], list(tag_conflicts))
356
385
 
357
386
    def test_merge_to_same_conflict_in_master_and_child(self):
358
387
        """When new_tags.merge_to(child.tags) conflicts the same way with the
365
394
        child = self.make_branch('child')
366
395
        child.bind(master)
367
396
        child.update()
368
 
        tag_conflicts = other.tags.merge_to(child.tags)
 
397
        tag_updates, tag_conflicts = other.tags.merge_to(child.tags)
369
398
        # Both master and child conflict, so both stay as rev-2
370
 
        self.assertEquals('rev-2', child.tags.lookup_tag('foo'))
371
 
        self.assertEquals('rev-2', master.tags.lookup_tag('foo'))
 
399
        self.assertEqual('rev-2', child.tags.lookup_tag('foo'))
 
400
        self.assertEqual('rev-2', master.tags.lookup_tag('foo'))
372
401
        # The conflict is reported exactly once, even though it occurs in both
373
402
        # master and child.
374
 
        self.assertEquals([(u'foo', 'rev-1', 'rev-2')], list(tag_conflicts))
 
403
        self.assertEqual({}, tag_updates)
 
404
        self.assertEqual([(u'foo', 'rev-1', 'rev-2')], list(tag_conflicts))
375
405
 
376
406
    def test_merge_to_different_conflict_in_master_and_child(self):
377
407
        """When new_tags.merge_to(child.tags) conflicts differently in the
387
417
        # We use the private method _set_tag_dict because normally bzr tries to
388
418
        # avoid this scenario.
389
419
        child.tags._set_tag_dict({'foo': 'rev-3'})
390
 
        tag_conflicts = other.tags.merge_to(child.tags)
 
420
        tag_updates, tag_conflicts = other.tags.merge_to(child.tags)
391
421
        # Both master and child conflict, so both stay as they were.
392
 
        self.assertEquals('rev-3', child.tags.lookup_tag('foo'))
393
 
        self.assertEquals('rev-2', master.tags.lookup_tag('foo'))
 
422
        self.assertEqual('rev-3', child.tags.lookup_tag('foo'))
 
423
        self.assertEqual('rev-2', master.tags.lookup_tag('foo'))
394
424
        # Both conflicts are reported.
395
 
        self.assertEquals(
 
425
        self.assertEqual({}, tag_updates)
 
426
        self.assertEqual(
396
427
            [(u'foo', 'rev-1', 'rev-2'), (u'foo', 'rev-1', 'rev-3')],
397
428
            sorted(tag_conflicts))
398
429
 
446
477
 
447
478
    def test_no_functions(self):
448
479
        rev = self.branch.last_revision()
449
 
        self.assertEquals(None, self.branch.automatic_tag_name(rev))
 
480
        self.assertEqual(None, self.branch.automatic_tag_name(rev))
450
481
 
451
482
    def test_returns_tag_name(self):
452
483
        def get_tag_name(br, revid):
453
484
            return "foo"
454
485
        branch.Branch.hooks.install_named_hook('automatic_tag_name',
455
486
            get_tag_name, 'get tag name foo')
456
 
        self.assertEquals("foo", self.branch.automatic_tag_name(
 
487
        self.assertEqual("foo", self.branch.automatic_tag_name(
457
488
            self.branch.last_revision()))
458
 
    
 
489
 
459
490
    def test_uses_first_return(self):
460
491
        get_tag_name_1 = lambda br, revid: "foo1"
461
492
        get_tag_name_2 = lambda br, revid: "foo2"
463
494
            get_tag_name_1, 'tagname1')
464
495
        branch.Branch.hooks.install_named_hook('automatic_tag_name',
465
496
            get_tag_name_2, 'tagname2')
466
 
        self.assertEquals("foo1", self.branch.automatic_tag_name(
 
497
        self.assertEqual("foo1", self.branch.automatic_tag_name(
467
498
            self.branch.last_revision()))
468
499
 
469
500
    def test_ignores_none(self):
473
504
            get_tag_name_1, 'tagname1')
474
505
        branch.Branch.hooks.install_named_hook('automatic_tag_name',
475
506
            get_tag_name_2, 'tagname2')
476
 
        self.assertEquals("foo2", self.branch.automatic_tag_name(
 
507
        self.assertEqual("foo2", self.branch.automatic_tag_name(
477
508
            self.branch.last_revision()))