/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
31
from .lazy_import import lazy_import
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
32
lazy_import(globals(), """
33
import itertools
34
import re
35
import sys
2220.2.14 by mbp at sourcefrog
cleanup
36
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
37
from breezy import (
2694.5.4 by Jelmer Vernooij
Move bzrlib.util.bencode to bzrlib._bencode_py.
38
    bencode,
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
39
    cleanup,
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
40
    errors,
2220.2.27 by Martin Pool
Start adding tags to Branch6
41
    trace,
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
42
    )
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
43
""")
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
44
45
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
46
class _Tags(object):
2220.2.28 by Martin Pool
Integrate tags with Branch6:
47
2220.2.14 by mbp at sourcefrog
cleanup
48
    def __init__(self, branch):
49
        self.branch = branch
50
6123.4.1 by Jelmer Vernooij
Add stubs.
51
    def get_tag_dict(self):
52
        """Return a dictionary mapping tags to revision ids.
53
        """
54
        raise NotImplementedError(self.get_tag_dict)
55
56
    def get_reverse_tag_dict(self):
57
        """Return a dictionary mapping revision ids to list of tags.
58
        """
59
        raise NotImplementedError(self.get_reverse_tag_dict)
60
61
    def merge_to(self, to_tags, overwrite=False, ignore_master=False):
62
        """Merge new tags from this tags container into another.
63
64
        :param to_tags: Tags container to merge into
65
        :param overwrite: Whether to overwrite existing, divergent, tags.
66
        :param ignore_master: Do not modify the tags in the target's master
67
            branch (if any).  Default is false (so the master will be updated).
68
            New in bzr 2.3.
69
        :return: Tuple with tag updates as dictionary and tag conflicts
70
        """
71
        raise NotImplementedError(self.merge_to)
72
73
    def set_tag(self, tag_name, revision):
74
        """Set a tag.
75
76
        :param tag_name: Tag name
77
        :param revision: Revision id
6123.4.2 by Jelmer Vernooij
Tags containers can indicate whether they support ghost tags.
78
        :raise GhostTagsNotSupported: if revision is not present in
79
            the branch repository
6123.4.1 by Jelmer Vernooij
Add stubs.
80
        """
81
        raise NotImplementedError(self.set_tag)
82
83
    def lookup_tag(self, tag_name):
84
        """Look up a tag.
85
86
        :param tag_name: Tag to look up
87
        :raise NoSuchTag: Raised when tag does not exist
88
        :return: Matching revision id
89
        """
90
        raise NotImplementedError(self.lookup_tag)
91
92
    def delete_tag(self, tag_name):
93
        """Delete a tag.
94
95
        :param tag_name: Tag to delete
96
        :raise NoSuchTag: Raised when tag does not exist
97
        """
98
        raise NotImplementedError(self.delete_tag)
99
100
    def rename_revisions(self, rename_map):
101
        """Replace revision ids according to a rename map.
102
103
        :param rename_map: Dictionary mapping old revision ids to
104
            new revision ids.
105
        """
106
        raise NotImplementedError(self.rename_revisions)
107
2220.2.42 by Martin Pool
Tag command refuses to replace existing tags unless you force it.
108
    def has_tag(self, tag_name):
6619.3.1 by Jelmer Vernooij
Apply 2to3 has_key fix.
109
        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.
110
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
111
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
112
class DisabledTags(_Tags):
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
113
    """Tag storage that refuses to store anything.
114
115
    This is used by older formats that can't store tags.
116
    """
117
118
    def _not_supported(self, *a, **k):
2220.2.14 by mbp at sourcefrog
cleanup
119
        raise errors.TagsNotSupported(self.branch)
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
120
121
    set_tag = _not_supported
122
    get_tag_dict = _not_supported
123
    _set_tag_dict = _not_supported
124
    lookup_tag = _not_supported
2220.2.21 by Martin Pool
Add tag --delete command and implementation
125
    delete_tag = _not_supported
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
126
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
127
    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
128
        # we never have anything to copy
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
129
        return {}, []
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
130
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
131
    def rename_revisions(self, rename_map):
132
        # No tags, so nothing to rename
133
        pass
134
2831.8.1 by James Westby
Fix log against smart server branches that don't support tags. (#140615)
135
    def get_reverse_tag_dict(self):
136
        # There aren't any tags, so the reverse mapping is empty.
137
        return {}
138
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
139
2220.2.20 by Martin Pool
Tag methods now available through Branch.tags.add_tag, etc
140
class BasicTags(_Tags):
2220.2.14 by mbp at sourcefrog
cleanup
141
    """Tag storage in an unversioned branch control file.
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
142
    """
143
144
    def set_tag(self, tag_name, tag_target):
2220.2.14 by mbp at sourcefrog
cleanup
145
        """Add a tag definition to the branch.
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
146
147
        Behaviour if the tag is already present is not defined (yet).
148
        """
149
        # all done with a write lock held, so this looks atomic
2220.2.14 by mbp at sourcefrog
cleanup
150
        self.branch.lock_write()
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
151
        try:
2805.5.2 by Martin Pool
Setting and deleting tags should also update the master branch, if any.
152
            master = self.branch.get_master_branch()
153
            if master is not None:
154
                master.tags.set_tag(tag_name, tag_target)
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
155
            td = self.get_tag_dict()
156
            td[tag_name] = tag_target
157
            self._set_tag_dict(td)
158
        finally:
2220.2.14 by mbp at sourcefrog
cleanup
159
            self.branch.unlock()
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
160
161
    def lookup_tag(self, tag_name):
162
        """Return the referent string of a tag"""
163
        td = self.get_tag_dict()
164
        try:
165
            return td[tag_name]
166
        except KeyError:
167
            raise errors.NoSuchTag(tag_name)
168
169
    def get_tag_dict(self):
2220.2.14 by mbp at sourcefrog
cleanup
170
        self.branch.lock_read()
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
171
        try:
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)
182
        finally:
2220.2.14 by mbp at sourcefrog
cleanup
183
            self.branch.unlock()
2388.1.11 by Alexander Belchenko
changes after John's review
184
2388.1.1 by Erik Bagfors
created reverse_tag_dict in tags.py
185
    def get_reverse_tag_dict(self):
186
        """Returns a dict with revisions as keys
187
           and a list of tags for that revision as value"""
188
        d = self.get_tag_dict()
189
        rev = {}
190
        for key in d:
191
            try:
192
                rev[d[key]].append(key)
193
            except KeyError:
194
                rev[d[key]] = [key]
195
        return rev
196
2220.2.21 by Martin Pool
Add tag --delete command and implementation
197
    def delete_tag(self, tag_name):
198
        """Delete a tag definition.
199
        """
200
        self.branch.lock_write()
201
        try:
202
            d = self.get_tag_dict()
203
            try:
204
                del d[tag_name]
205
            except KeyError:
206
                raise errors.NoSuchTag(tag_name)
2805.5.2 by Martin Pool
Setting and deleting tags should also update the master branch, if any.
207
            master = self.branch.get_master_branch()
208
            if master is not None:
209
                try:
210
                    master.tags.delete_tag(tag_name)
211
                except errors.NoSuchTag:
212
                    pass
2220.2.21 by Martin Pool
Add tag --delete command and implementation
213
            self._set_tag_dict(d)
214
        finally:
215
            self.branch.unlock()
216
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
217
    def _set_tag_dict(self, new_dict):
218
        """Replace all tag definitions
219
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.
220
        WARNING: Calling this on an unlocked branch will lock it, and will
221
        replace the tags without warning on conflicts.
222
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
223
        :param new_dict: Dictionary from tag name to target.
224
        """
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.
225
        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
226
227
    def _serialize_tag_dict(self, tag_dict):
2220.2.21 by Martin Pool
Add tag --delete command and implementation
228
        td = dict((k.encode('utf-8'), v)
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
229
                  for k, v in tag_dict.items())
2220.2.21 by Martin Pool
Add tag --delete command and implementation
230
        return bencode.bencode(td)
2220.2.11 by mbp at sourcefrog
Get tag tests working again, stored in the Branch
231
232
    def _deserialize_tag_dict(self, tag_content):
233
        """Convert the tag file into a dictionary of tags"""
2220.2.28 by Martin Pool
Integrate tags with Branch6:
234
        # 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
235
        # is an empty dictionary
236
        if tag_content == '':
237
            return {}
238
        try:
2220.2.21 by Martin Pool
Add tag --delete command and implementation
239
            r = {}
240
            for k, v in bencode.bdecode(tag_content).items():
241
                r[k.decode('utf-8')] = v
242
            return r
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
243
        except ValueError as e:
2220.2.21 by Martin Pool
Add tag --delete command and implementation
244
            raise ValueError("failed to deserialize tag dictionary %r: %s"
2220.2.32 by Martin Pool
Slightly smarter tag merge
245
                % (tag_content, e))
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
246
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
247
    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
248
        """Copy tags between repositories if necessary and possible.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
249
250
        This method has common command-line behaviour about handling
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
251
        error cases.
252
2220.2.32 by Martin Pool
Slightly smarter tag merge
253
        All new definitions are copied across, except that tags that already
254
        exist keep their existing definitions.
255
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
256
        :param to_tags: Branch to receive these tags
2804.3.1 by Lukáš Lalinský
Overwrite conflicting tags by push|pull --overwrite.
257
        :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.
258
        :param ignore_master: Do not modify the tags in the target's master
259
            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.
260
            New in bzr 2.3.
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
261
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
262
        :returns: Tuple with tag_updates and tag_conflicts.
263
            tag_updates is a dictionary with new tags, None is used for
264
            removed tags
265
            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.
266
            (tagname, source_target, dest_target), or None if no copying was
267
            done.
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
268
        """
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
269
        operation = cleanup.OperationWithCleanups(self._merge_to_operation)
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
270
        return operation.run(to_tags, overwrite, ignore_master)
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
271
5050.53.4 by Andrew Bennetts
Don't propagate tags to the master branch during cmd_merge.
272
    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.
273
        add_cleanup = operation.add_cleanup
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
274
        if self.branch == to_tags.branch:
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
275
            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.
276
        if not self.branch.supports_tags():
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
277
            # obviously nothing to copy
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
278
            return {}, []
2220.2.32 by Martin Pool
Slightly smarter tag merge
279
        source_dict = self.get_tag_dict()
280
        if not source_dict:
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
281
            # no tags in the source, and we don't want to clobber anything
282
            # that's in the destination
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
283
            return {}, []
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
284
        # 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.
285
        #
286
        # 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.
287
        # tags, in which case it's possible to have different sets of
288
        # conflicts.  We report the union of both conflict sets.  In
289
        # 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.
290
        # different tags from the source, which may be a surprising result, but
291
        # the best we can do in the circumstances.
292
        #
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
293
        # Ideally we'd improve this API to report the different conflicts
294
        # more clearly to the caller, but we don't want to break plugins
295
        # such as bzr-builddeb that use this API.
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
296
        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.
297
        if ignore_master:
298
            master = None
299
        else:
300
            master = to_tags.branch.get_master_branch()
5050.53.3 by Andrew Bennetts
Use add_cleanup for simpler and more correct unlocking.
301
        if master is not None:
302
            add_cleanup(master.lock_write().unlock)
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
303
        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.
304
        if master is not None:
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
305
            extra_updates, extra_conflicts = self._merge_to(master.tags,
306
                source_dict, overwrite)
307
            updates.update(extra_updates)
308
            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.
309
        # 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.
310
        # branch.
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
311
        return updates, set(conflicts)
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
312
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
313
    def _merge_to(self, to_tags, source_dict, overwrite):
314
        dest_dict = to_tags.get_tag_dict()
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
315
        result, updates, conflicts = self._reconcile_tags(source_dict,
316
            dest_dict, overwrite)
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
317
        if result != dest_dict:
318
            to_tags._set_tag_dict(result)
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
319
        return updates, conflicts
5050.53.1 by Andrew Bennetts
Tags.merge_to now updates the master branch as well, if any.
320
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
321
    def rename_revisions(self, rename_map):
322
        """Rename revisions in this tags dictionary.
6123.4.1 by Jelmer Vernooij
Add stubs.
323
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
324
        :param rename_map: Dictionary mapping old revids to new revids
325
        """
326
        reverse_tags = self.get_reverse_tag_dict()
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
327
        for revid, names in reverse_tags.items():
4325.2.1 by Jelmer Vernooij
Add Tags.rename_revisions().
328
            if revid in rename_map:
329
                for name in names:
330
                    self.set_tag(name, rename_map[revid])
331
2804.3.1 by Lukáš Lalinský
Overwrite conflicting tags by push|pull --overwrite.
332
    def _reconcile_tags(self, source_dict, dest_dict, overwrite):
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
333
        """Do a two-way merge of two tag dictionaries.
334
5891.1.2 by Andrew Bennetts
Fix a bunch of docstring formatting nits, making pydoctor a bit happier.
335
        * only in source => source value
336
        * only in destination => destination value
337
        * same definitions => that
338
        * different definitions => if overwrite is False, keep destination
339
          value and give a warning, otherwise use the source value
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
340
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
341
        :returns: (result_dict, updates,
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
342
            [(conflicting_tag, source_target, dest_target)])
343
        """
344
        conflicts = []
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
345
        updates = {}
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
346
        result = dict(dest_dict) # copy
347
        for name, target in source_dict.items():
6156.1.2 by Jelmer Vernooij
Fix tests.
348
            if result.get(name) == target:
349
                pass
350
            elif name not in result or overwrite:
351
                updates[name] = target
2220.2.33 by Martin Pool
Start support for flagging tag conflicts
352
                result[name] = target
353
            else:
354
                conflicts.append((name, target, result[name]))
6112.4.1 by Jelmer Vernooij
Show how many tags have been updated in bzr pull.
355
        return result, updates, conflicts
2220.2.32 by Martin Pool
Slightly smarter tag merge
356
2220.2.30 by Martin Pool
split out tag-merging code and add some tests
357
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
358
def sort_natural(branch, tags):
359
    """Sort tags, with numeric substrings as numbers.
360
361
    :param branch: Branch
362
    :param tags: List of tuples with tag name and revision id.
363
    """
364
    def natural_sort_key(tag):
365
        return [f(s) for f,s in
366
                zip(itertools.cycle((unicode.lower,int)),
367
                                    re.split('([0-9]+)', tag[0]))]
368
    tags.sort(key=natural_sort_key)
369
370
371
def sort_alpha(branch, tags):
372
    """Sort tags lexicographically, in place.
373
374
    :param branch: Branch
375
    :param tags: List of tuples with tag name and revision id.
376
    """
377
    tags.sort()
378
379
380
def sort_time(branch, tags):
381
    """Sort tags by time inline.
382
383
    :param branch: Branch
384
    :param tags: List of tuples with tag name and revision id.
385
    """
386
    timestamps = {}
387
    for tag, revid in tags:
388
        try:
389
            revobj = branch.repository.get_revision(revid)
390
        except errors.NoSuchRevision:
6619.3.22 by Jelmer Vernooij
apply 2to3 renames fix.
391
            timestamp = sys.maxsize # place them at the end
5582.2.1 by Jelmer Vernooij
support extending --sort argument to 'bzr tags'.
392
        else:
393
            timestamp = revobj.timestamp
394
        timestamps[revid] = timestamp
395
    tags.sort(key=lambda x: timestamps[x[1]])
396
397
398
tag_sort_methods = Registry()
399
tag_sort_methods.register("natural", sort_natural,
400
    'Sort numeric substrings as numbers. (default)')
401
tag_sort_methods.register("alpha", sort_alpha, 'Sort tags lexicographically.')
402
tag_sort_methods.register("time", sort_time, 'Sort tags chronologically.')
403
tag_sort_methods.default_key = "natural"