/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2007-2011 Canonical Ltd
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
16
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
17
"""Tag strategies.
18
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
19
These are contained within a branch and normally constructed
20
when the branch is opened.  Clients should typically do
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
21
22
  Branch.tags.add('name', 'value')
23
"""
24
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
25
from __future__ import absolute_import
26
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
27
# NOTE: I was going to call this tags.py, but vim seems to think all files
28
# called tags* are ctags files... mbp 20070220.
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
29
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
30
from .registry import Registry
6973.6.2 by Jelmer Vernooij
Fix more tests.
31
from .sixish import text_type
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
32
from .lazy_import import lazy_import
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
33
lazy_import(globals(), """
34
import itertools
35
import re
36
import sys
2220.2.14 by mbp at sourcefrog
cleanup
37
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
38
from breezy import (
2694.5.4 by Jelmer Vernooij
Move bzrlib.util.bencode to bzrlib._bencode_py.
39
    bencode,
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
40
    cleanup,
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
41
    errors,
2220.2.27 by Martin Pool
Start adding tags to Branch6
42
    trace,
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
43
    )
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
44
""")
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
45
46
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
47
class _Tags(object):
2220.2.28 by Martin Pool
Integrate tags with Branch6:
48
2220.2.14 by mbp at sourcefrog
cleanup
49
    def __init__(self, branch):
50
        self.branch = branch
51
6123.4.1 by Jelmer Vernooij
Add stubs.
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
6123.4.2 by Jelmer Vernooij
Tags containers can indicate whether they support ghost tags.
79
        :raise GhostTagsNotSupported: if revision is not present in
80
            the branch repository
6123.4.1 by Jelmer Vernooij
Add stubs.
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
2220.2.42 by Martin Pool
Tag command refuses to replace existing tags unless you force it.
109
    def has_tag(self, tag_name):
6619.3.1 by Jelmer Vernooij
Apply 2to3 has_key fix.
110
        return tag_name in self.get_tag_dict()
2220.2.42 by Martin Pool
Tag command refuses to replace existing tags unless you force it.
111
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
112
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
113
class DisabledTags(_Tags):
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
114
    """Tag storage that refuses to store anything.
115
116
    This is used by older formats that can't store tags.
117
    """
118
119
    def _not_supported(self, *a, **k):
2220.2.14 by mbp at sourcefrog
cleanup
120
        raise errors.TagsNotSupported(self.branch)
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
121
122
    set_tag = _not_supported
123
    get_tag_dict = _not_supported
124
    _set_tag_dict = _not_supported
125
    lookup_tag = _not_supported
2220.2.21 by Martin Pool
Add tag --delete command and implementation
126
    delete_tag = _not_supported
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
127
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
128
    def merge_to(self, to_tags, overwrite=False, ignore_master=False):
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
129
        # we never have anything to copy
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
130
        return {}, []
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
131
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
132
    def rename_revisions(self, rename_map):
133
        # No tags, so nothing to rename
134
        pass
135
2831.8.1 by James Westby
Fix log against smart server branches that don't support tags. (#140615)
136
    def get_reverse_tag_dict(self):
137
        # There aren't any tags, so the reverse mapping is empty.
138
        return {}
139
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
140
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
141
class BasicTags(_Tags):
2220.2.14 by mbp at sourcefrog
cleanup
142
    """Tag storage in an unversioned branch control file.
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
143
    """
144
145
    def set_tag(self, tag_name, tag_target):
2220.2.14 by mbp at sourcefrog
cleanup
146
        """Add a tag definition to the branch.
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
147
148
        Behaviour if the tag is already present is not defined (yet).
149
        """
150
        # all done with a write lock held, so this looks atomic
2220.2.14 by mbp at sourcefrog
cleanup
151
        self.branch.lock_write()
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
152
        try:
2805.5.2 by Martin Pool
Setting and deleting tags should also update the master branch, if any.
153
            master = self.branch.get_master_branch()
154
            if master is not None:
155
                master.tags.set_tag(tag_name, tag_target)
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
156
            td = self.get_tag_dict()
157
            td[tag_name] = tag_target
158
            self._set_tag_dict(td)
159
        finally:
2220.2.14 by mbp at sourcefrog
cleanup
160
            self.branch.unlock()
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
161
162
    def lookup_tag(self, tag_name):
163
        """Return the referent string of a tag"""
164
        td = self.get_tag_dict()
165
        try:
166
            return td[tag_name]
167
        except KeyError:
168
            raise errors.NoSuchTag(tag_name)
169
170
    def get_tag_dict(self):
6754.8.4 by Jelmer Vernooij
Use new context stuff.
171
        with self.branch.lock_read():
2220.2.27 by Martin Pool
Start adding tags to Branch6
172
            try:
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
173
                tag_content = self.branch._get_tags_bytes()
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
174
            except errors.NoSuchFile as e:
2220.2.28 by Martin Pool
Integrate tags with Branch6:
175
                # ugly, but only abentley should see this :)
176
                trace.warning('No branch/tags file in %s.  '
2220.2.27 by Martin Pool
Start adding tags to Branch6
177
                     'This branch was probably created by bzr 0.15pre.  '
2220.2.28 by Martin Pool
Integrate tags with Branch6:
178
                     'Create an empty file to silence this message.'
179
                     % (self.branch, ))
2220.2.27 by Martin Pool
Start adding tags to Branch6
180
                return {}
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
181
            return self._deserialize_tag_dict(tag_content)
2388.1.11 by Alexander Belchenko
changes after John's review
182
2388.1.1 by Erik Bagfors
created reverse_tag_dict in tags.py
183
    def get_reverse_tag_dict(self):
184
        """Returns a dict with revisions as keys
185
           and a list of tags for that revision as value"""
186
        d = self.get_tag_dict()
187
        rev = {}
188
        for key in d:
189
            try:
190
                rev[d[key]].append(key)
191
            except KeyError:
192
                rev[d[key]] = [key]
193
        return rev
194
2220.2.21 by Martin Pool
Add tag --delete command and implementation
195
    def delete_tag(self, tag_name):
196
        """Delete a tag definition.
197
        """
198
        self.branch.lock_write()
199
        try:
200
            d = self.get_tag_dict()
201
            try:
202
                del d[tag_name]
203
            except KeyError:
204
                raise errors.NoSuchTag(tag_name)
2805.5.2 by Martin Pool
Setting and deleting tags should also update the master branch, if any.
205
            master = self.branch.get_master_branch()
206
            if master is not None:
207
                try:
208
                    master.tags.delete_tag(tag_name)
209
                except errors.NoSuchTag:
210
                    pass
2220.2.21 by Martin Pool
Add tag --delete command and implementation
211
            self._set_tag_dict(d)
212
        finally:
213
            self.branch.unlock()
214
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
215
    def _set_tag_dict(self, new_dict):
216
        """Replace all tag definitions
217
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
218
        WARNING: Calling this on an unlocked branch will lock it, and will
219
        replace the tags without warning on conflicts.
220
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
221
        :param new_dict: Dictionary from tag name to target.
222
        """
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
223
        return self.branch._set_tags_bytes(self._serialize_tag_dict(new_dict))
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
224
225
    def _serialize_tag_dict(self, tag_dict):
2220.2.21 by Martin Pool
Add tag --delete command and implementation
226
        td = dict((k.encode('utf-8'), v)
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
227
                  for k, v in tag_dict.items())
2220.2.21 by Martin Pool
Add tag --delete command and implementation
228
        return bencode.bencode(td)
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
229
230
    def _deserialize_tag_dict(self, tag_content):
231
        """Convert the tag file into a dictionary of tags"""
2220.2.28 by Martin Pool
Integrate tags with Branch6:
232
        # was a special case to make initialization easy, an empty definition
2220.2.15 by mbp at sourcefrog
Store tag dictionary in bencode and accomodate non-ascii tags
233
        # is an empty dictionary
6963.1.1 by Jelmer Vernooij
Fix a bunch of tests on python3.
234
        if tag_content == b'':
2220.2.15 by mbp at sourcefrog
Store tag dictionary in bencode and accomodate non-ascii tags
235
            return {}
236
        try:
2220.2.21 by Martin Pool
Add tag --delete command and implementation
237
            r = {}
238
            for k, v in bencode.bdecode(tag_content).items():
239
                r[k.decode('utf-8')] = v
240
            return r
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
241
        except ValueError as e:
2220.2.21 by Martin Pool
Add tag --delete command and implementation
242
            raise ValueError("failed to deserialize tag dictionary %r: %s"
2220.2.32 by Martin Pool
Slightly smarter tag merge
243
                % (tag_content, e))
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
244
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
245
    def merge_to(self, to_tags, overwrite=False, ignore_master=False):
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
246
        """Copy tags between repositories if necessary and possible.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
247
248
        This method has common command-line behaviour about handling
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
249
        error cases.
250
2220.2.32 by Martin Pool
Slightly smarter tag merge
251
        All new definitions are copied across, except that tags that already
252
        exist keep their existing definitions.
253
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
254
        :param to_tags: Branch to receive these tags
2804.3.1 by Lukáš Lalinský
Overwrite conflicting tags by push|pull --overwrite.
255
        :param overwrite: Overwrite conflicting tags in the target branch
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
256
        :param ignore_master: Do not modify the tags in the target's master
257
            branch (if any).  Default is false (so the master will be updated).
5540.4.2 by Andrew Bennetts
Remove references to 2.2.2 in comments and warnings: this patch was not accepted for 2.2.
258
            New in bzr 2.3.
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
259
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
260
        :returns: Tuple with tag_updates and tag_conflicts.
261
            tag_updates is a dictionary with new tags, None is used for
262
            removed tags
263
            tag_conflicts is a set of tags that conflicted, each of which is
3482.1.1 by John Arbash Meinel
Fix bug #238149, RemoteBranch.pull needs to return the _real_branch's pull result.
264
            (tagname, source_target, dest_target), or None if no copying was
265
            done.
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
266
        """
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
267
        operation = cleanup.OperationWithCleanups(self._merge_to_operation)
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
268
        return operation.run(to_tags, overwrite, ignore_master)
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
269
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
270
    def _merge_to_operation(self, operation, to_tags, overwrite, ignore_master):
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
271
        add_cleanup = operation.add_cleanup
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
272
        if self.branch == to_tags.branch:
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
273
            return {}, []
4084.2.1 by Robert Collins
Make accessing a branch.tags.get_tag_dict use a smart[er] method rather than VFS calls and real objects.
274
        if not self.branch.supports_tags():
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
275
            # obviously nothing to copy
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
276
            return {}, []
2220.2.32 by Martin Pool
Slightly smarter tag merge
277
        source_dict = self.get_tag_dict()
278
        if not source_dict:
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
279
            # no tags in the source, and we don't want to clobber anything
280
            # that's in the destination
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
281
            return {}, []
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
282
        # We merge_to both master and child individually.
5050.53.2 by Andrew Bennetts
More tests, more description of test intent, and specify exactly what happens with duplicate vs. different conflicts.
283
        #
284
        # It's possible for master and child to have differing sets of
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
285
        # tags, in which case it's possible to have different sets of
286
        # conflicts.  We report the union of both conflict sets.  In
287
        # that case it's likely the child and master have accepted
5050.53.2 by Andrew Bennetts
More tests, more description of test intent, and specify exactly what happens with duplicate vs. different conflicts.
288
        # different tags from the source, which may be a surprising result, but
289
        # the best we can do in the circumstances.
290
        #
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
291
        # Ideally we'd improve this API to report the different conflicts
292
        # more clearly to the caller, but we don't want to break plugins
293
        # such as bzr-builddeb that use this API.
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
294
        add_cleanup(to_tags.branch.lock_write().unlock)
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
295
        if ignore_master:
296
            master = None
297
        else:
298
            master = to_tags.branch.get_master_branch()
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
299
        if master is not None:
300
            add_cleanup(master.lock_write().unlock)
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
301
        updates, conflicts = self._merge_to(to_tags, source_dict, overwrite)
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
302
        if master is not None:
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
303
            extra_updates, extra_conflicts = self._merge_to(master.tags,
304
                source_dict, overwrite)
305
            updates.update(extra_updates)
306
            conflicts += extra_conflicts
5050.53.2 by Andrew Bennetts
More tests, more description of test intent, and specify exactly what happens with duplicate vs. different conflicts.
307
        # We use set() to remove any duplicate conflicts from the master
5540.4.3 by Andrew Bennetts
Simplify slightly, we don't need to be quite so paranoid about API breakage in the development branch.
308
        # branch.
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
309
        return updates, set(conflicts)
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
310
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
311
    def _merge_to(self, to_tags, source_dict, overwrite):
312
        dest_dict = to_tags.get_tag_dict()
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
313
        result, updates, conflicts = self._reconcile_tags(source_dict,
314
            dest_dict, overwrite)
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
315
        if result != dest_dict:
316
            to_tags._set_tag_dict(result)
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
317
        return updates, conflicts
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
318
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
319
    def rename_revisions(self, rename_map):
320
        """Rename revisions in this tags dictionary.
6123.4.1 by Jelmer Vernooij
Add stubs.
321
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
322
        :param rename_map: Dictionary mapping old revids to new revids
323
        """
324
        reverse_tags = self.get_reverse_tag_dict()
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
325
        for revid, names in reverse_tags.items():
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
326
            if revid in rename_map:
327
                for name in names:
328
                    self.set_tag(name, rename_map[revid])
329
2804.3.1 by Lukáš Lalinský
Overwrite conflicting tags by push|pull --overwrite.
330
    def _reconcile_tags(self, source_dict, dest_dict, overwrite):
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
331
        """Do a two-way merge of two tag dictionaries.
332
5891.1.2 by Andrew Bennetts
Fix a bunch of docstring formatting nits, making pydoctor a bit happier.
333
        * only in source => source value
334
        * only in destination => destination value
335
        * same definitions => that
336
        * different definitions => if overwrite is False, keep destination
337
          value and give a warning, otherwise use the source value
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
338
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
339
        :returns: (result_dict, updates,
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
340
            [(conflicting_tag, source_target, dest_target)])
341
        """
342
        conflicts = []
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
343
        updates = {}
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
344
        result = dict(dest_dict) # copy
345
        for name, target in source_dict.items():
6156.1.2 by Jelmer Vernooij
Fix tests.
346
            if result.get(name) == target:
347
                pass
348
            elif name not in result or overwrite:
349
                updates[name] = target
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
350
                result[name] = target
351
            else:
352
                conflicts.append((name, target, result[name]))
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
353
        return result, updates, conflicts
2220.2.32 by Martin Pool
Slightly smarter tag merge
354
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
355
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
356
def sort_natural(branch, tags):
357
    """Sort tags, with numeric substrings as numbers.
358
359
    :param branch: Branch
360
    :param tags: List of tuples with tag name and revision id.
361
    """
362
    def natural_sort_key(tag):
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
363
        return [f(s) for f, s in
6973.6.2 by Jelmer Vernooij
Fix more tests.
364
                zip(itertools.cycle((text_type.lower, int)),
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
365
                                    re.split('([0-9]+)', tag[0]))]
366
    tags.sort(key=natural_sort_key)
367
368
369
def sort_alpha(branch, tags):
370
    """Sort tags lexicographically, in place.
371
372
    :param branch: Branch
373
    :param tags: List of tuples with tag name and revision id.
374
    """
375
    tags.sort()
376
377
378
def sort_time(branch, tags):
379
    """Sort tags by time inline.
380
381
    :param branch: Branch
382
    :param tags: List of tuples with tag name and revision id.
383
    """
384
    timestamps = {}
385
    for tag, revid in tags:
386
        try:
387
            revobj = branch.repository.get_revision(revid)
388
        except errors.NoSuchRevision:
6619.3.22 by Jelmer Vernooij
apply 2to3 renames fix.
389
            timestamp = sys.maxsize # place them at the end
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
390
        else:
391
            timestamp = revobj.timestamp
392
        timestamps[revid] = timestamp
393
    tags.sort(key=lambda x: timestamps[x[1]])
394
395
396
tag_sort_methods = Registry()
397
tag_sort_methods.register("natural", sort_natural,
398
    'Sort numeric substrings as numbers. (default)')
399
tag_sort_methods.register("alpha", sort_alpha, 'Sort tags lexicographically.')
400
tag_sort_methods.register("time", sort_time, 'Sort tags chronologically.')
401
tag_sort_methods.default_key = "natural"