~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tag.py

  • Committer: Jelmer Vernooij
  • Date: 2012-02-20 12:19:29 UTC
  • mfrom: (6437.23.11 2.5)
  • mto: (6581.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 6582.
  • Revision ID: jelmer@samba.org-20120220121929-7ni2psvjoatm1yp4
Merge bzr/2.5.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
  Branch.tags.add('name', 'value')
23
23
"""
24
24
 
 
25
from __future__ import absolute_import
 
26
 
25
27
# NOTE: I was going to call this tags.py, but vim seems to think all files
26
28
# called tags* are ctags files... mbp 20070220.
27
29
 
47
49
    def __init__(self, branch):
48
50
        self.branch = branch
49
51
 
 
52
    def get_tag_dict(self):
 
53
        """Return a dictionary mapping tags to revision ids.
 
54
        """
 
55
        raise NotImplementedError(self.get_tag_dict)
 
56
 
 
57
    def get_reverse_tag_dict(self):
 
58
        """Return a dictionary mapping revision ids to list of tags.
 
59
        """
 
60
        raise NotImplementedError(self.get_reverse_tag_dict)
 
61
 
 
62
    def merge_to(self, to_tags, overwrite=False, ignore_master=False):
 
63
        """Merge new tags from this tags container into another.
 
64
 
 
65
        :param to_tags: Tags container to merge into
 
66
        :param overwrite: Whether to overwrite existing, divergent, tags.
 
67
        :param ignore_master: Do not modify the tags in the target's master
 
68
            branch (if any).  Default is false (so the master will be updated).
 
69
            New in bzr 2.3.
 
70
        :return: Tuple with tag updates as dictionary and tag conflicts
 
71
        """
 
72
        raise NotImplementedError(self.merge_to)
 
73
 
 
74
    def set_tag(self, tag_name, revision):
 
75
        """Set a tag.
 
76
 
 
77
        :param tag_name: Tag name
 
78
        :param revision: Revision id
 
79
        :raise GhostTagsNotSupported: if revision is not present in
 
80
            the branch repository
 
81
        """
 
82
        raise NotImplementedError(self.set_tag)
 
83
 
 
84
    def lookup_tag(self, tag_name):
 
85
        """Look up a tag.
 
86
 
 
87
        :param tag_name: Tag to look up
 
88
        :raise NoSuchTag: Raised when tag does not exist
 
89
        :return: Matching revision id
 
90
        """
 
91
        raise NotImplementedError(self.lookup_tag)
 
92
 
 
93
    def delete_tag(self, tag_name):
 
94
        """Delete a tag.
 
95
 
 
96
        :param tag_name: Tag to delete
 
97
        :raise NoSuchTag: Raised when tag does not exist
 
98
        """
 
99
        raise NotImplementedError(self.delete_tag)
 
100
 
 
101
    def rename_revisions(self, rename_map):
 
102
        """Replace revision ids according to a rename map.
 
103
 
 
104
        :param rename_map: Dictionary mapping old revision ids to
 
105
            new revision ids.
 
106
        """
 
107
        raise NotImplementedError(self.rename_revisions)
 
108
 
50
109
    def has_tag(self, tag_name):
51
110
        return self.get_tag_dict().has_key(tag_name)
52
111
 
68
127
 
69
128
    def merge_to(self, to_tags, overwrite=False, ignore_master=False):
70
129
        # we never have anything to copy
71
 
        pass
 
130
        return {}, []
72
131
 
73
132
    def rename_revisions(self, rename_map):
74
133
        # No tags, so nothing to rename
201
260
            branch (if any).  Default is false (so the master will be updated).
202
261
            New in bzr 2.3.
203
262
 
204
 
        :returns: A set of tags that conflicted, each of which is
 
263
        :returns: Tuple with tag_updates and tag_conflicts.
 
264
            tag_updates is a dictionary with new tags, None is used for
 
265
            removed tags
 
266
            tag_conflicts is a set of tags that conflicted, each of which is
205
267
            (tagname, source_target, dest_target), or None if no copying was
206
268
            done.
207
269
        """
211
273
    def _merge_to_operation(self, operation, to_tags, overwrite, ignore_master):
212
274
        add_cleanup = operation.add_cleanup
213
275
        if self.branch == to_tags.branch:
214
 
            return
 
276
            return {}, []
215
277
        if not self.branch.supports_tags():
216
278
            # obviously nothing to copy
217
 
            return
 
279
            return {}, []
218
280
        source_dict = self.get_tag_dict()
219
281
        if not source_dict:
220
282
            # no tags in the source, and we don't want to clobber anything
221
283
            # that's in the destination
222
 
            return
 
284
            return {}, []
223
285
        # We merge_to both master and child individually.
224
286
        #
225
287
        # It's possible for master and child to have differing sets of
239
301
            master = to_tags.branch.get_master_branch()
240
302
        if master is not None:
241
303
            add_cleanup(master.lock_write().unlock)
242
 
        conflicts = self._merge_to(to_tags, source_dict, overwrite)
 
304
        updates, conflicts = self._merge_to(to_tags, source_dict, overwrite)
243
305
        if master is not None:
244
 
            conflicts += self._merge_to(master.tags, source_dict,
245
 
                overwrite)
 
306
            extra_updates, extra_conflicts = self._merge_to(master.tags,
 
307
                source_dict, overwrite)
 
308
            updates.update(extra_updates)
 
309
            conflicts += extra_conflicts
246
310
        # We use set() to remove any duplicate conflicts from the master
247
311
        # branch.
248
 
        return set(conflicts)
 
312
        return updates, set(conflicts)
249
313
 
250
314
    def _merge_to(self, to_tags, source_dict, overwrite):
251
315
        dest_dict = to_tags.get_tag_dict()
252
 
        result, conflicts = self._reconcile_tags(source_dict, dest_dict,
253
 
                                                 overwrite)
 
316
        result, updates, conflicts = self._reconcile_tags(source_dict,
 
317
            dest_dict, overwrite)
254
318
        if result != dest_dict:
255
319
            to_tags._set_tag_dict(result)
256
 
        return conflicts
 
320
        return updates, conflicts
257
321
 
258
322
    def rename_revisions(self, rename_map):
259
323
        """Rename revisions in this tags dictionary.
260
 
        
 
324
 
261
325
        :param rename_map: Dictionary mapping old revids to new revids
262
326
        """
263
327
        reverse_tags = self.get_reverse_tag_dict()
275
339
        * different definitions => if overwrite is False, keep destination
276
340
          value and give a warning, otherwise use the source value
277
341
 
278
 
        :returns: (result_dict,
 
342
        :returns: (result_dict, updates,
279
343
            [(conflicting_tag, source_target, dest_target)])
280
344
        """
281
345
        conflicts = []
 
346
        updates = {}
282
347
        result = dict(dest_dict) # copy
283
348
        for name, target in source_dict.items():
284
 
            if name not in result or overwrite:
 
349
            if result.get(name) == target:
 
350
                pass
 
351
            elif name not in result or overwrite:
 
352
                updates[name] = target
285
353
                result[name] = target
286
 
            elif result[name] == target:
287
 
                pass
288
354
            else:
289
355
                conflicts.append((name, target, result[name]))
290
 
        return result, conflicts
 
356
        return result, updates, conflicts
291
357
 
292
358
 
293
359
def _merge_tags_if_possible(from_branch, to_branch, ignore_master=False):