~abentley/bzrtools/bzrtools.dev

0.9.11 by Alexander Belchenko
Added GPL header
1
# Written by Alexander Belchenko
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
2
# based on Robert Collins code
0.9.11 by Alexander Belchenko
Added GPL header
3
#
4
#    This program is free software; you can redistribute it and/or modify
5
#    it under the terms of the GNU General Public License as published by
6
#    the Free Software Foundation; either version 2 of the License, or
7
#    (at your option) any later version.
8
#
9
#    This program is distributed in the hope that it will be useful,
10
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
#    GNU General Public License for more details.
13
#
14
#    You should have received a copy of the GNU General Public License
15
#    along with this program; if not, write to the Free Software
16
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
17
0.9.2 by Wouter van Heyst
also work when in a branch
18
"""Show all 'heads' in a repository"""
19
20
0.9.14 by Alexander Belchenko
bzrtool's iter_branches is too slow. Added --debug-time feature show this fact
21
import time
22
0.9.17 by Alexander Belchenko
Restored support for running from standalone branch or not from root of shared repo
23
import bzrlib
776.2.1 by Jelmer Vernooij
Remove unused imports and fix two imports.
24
from bzrlib.commands import Command, display_command
0.9.17 by Alexander Belchenko
Restored support for running from standalone branch or not from root of shared repo
25
from bzrlib import errors
0.9.10 by Alexander Belchenko
Implemented sort by date
26
from bzrlib.option import Option
0.9.27 by Aaron Bentley
Support remote locations
27
from bzrlib.urlutils import unescape_for_display
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
28
29
30
class cmd_heads(Command):
0.9.2 by Wouter van Heyst
also work when in a branch
31
    """Show all revisions in a repository not having descendants.
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
32
    """
0.9.25 by Aaron Bentley
Update option grammar
33
    takes_options = [Option('by-date',
34
                     help='Sort heads by date (descending).'),
35
                     Option('all', help='Show all heads (dead and alive).'),
36
                     Option('dead-only', help='Show only dead heads.'),
37
                     Option('tips', help='Show tips of all branches.'),
38
                     Option('debug-time',
39
                     help='Enable debug print of operations times.'),
0.9.10 by Alexander Belchenko
Implemented sort by date
40
                    ]
41
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
42
    encoding_type = "replace"
0.9.27 by Aaron Bentley
Support remote locations
43
    takes_args = ['location?']
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
44
45
    @display_command
0.9.27 by Aaron Bentley
Support remote locations
46
    def run(self, by_date=False, all=False, dead_only=False, tips=False,
47
            debug_time=False, location='.'):
0.9.21 by Alexander Belchenko
fix usage of bzrlib.branch without explicit import
48
        import bzrlib.branch
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
49
        from bzrlib.osutils import format_date
50
        import bzrlib.repository
0.9.4 by Alexander Belchenko
- Use different return codes for differnet cases
51
0.9.14 by Alexander Belchenko
bzrtool's iter_branches is too slow. Added --debug-time feature show this fact
52
        self._init_elapsed_time(debug_time)
53
0.9.4 by Alexander Belchenko
- Use different return codes for differnet cases
54
        to_file = self.outf
55
0.9.13 by Alexander Belchenko
implemented select of heads by dead/alive mark
56
        branch = None
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
57
        try:
0.9.27 by Aaron Bentley
Support remote locations
58
            branch = bzrlib.branch.Branch.open_containing(location)[0]
0.9.13 by Alexander Belchenko
implemented select of heads by dead/alive mark
59
            repo = branch.repository
0.9.2 by Wouter van Heyst
also work when in a branch
60
        except errors.NotBranchError:
61
            try:
0.9.27 by Aaron Bentley
Support remote locations
62
                repo = bzrlib.repository.Repository.open(location)
0.9.2 by Wouter van Heyst
also work when in a branch
63
            except errors.NotBranchError:
0.9.4 by Alexander Belchenko
- Use different return codes for differnet cases
64
                print >>to_file, \
65
                      ("You need to run this command "
66
                       "either from the root of a shared repository,\n"
0.9.2 by Wouter van Heyst
also work when in a branch
67
                       "or from a branch.")
0.9.4 by Alexander Belchenko
- Use different return codes for differnet cases
68
                return 3
0.9.22 by Aaron Bentley
Improve heads performance
69
        repo.lock_read()
70
        try:
639 by Aaron Bentley
Avoid using deprecated interface for heads
71
            possible_heads = set(repo.all_revision_ids())
72
            g = repo.get_graph().get_parent_map(possible_heads)
0.9.22 by Aaron Bentley
Improve heads performance
73
            not_heads = set()
74
            for parents in g.values():
75
                not_heads.update(set(parents))
76
77
            self.heads = possible_heads.difference(not_heads)
78
79
            # TODO: use different sorting schemes instead of alphabetical sort
80
            self.heads = list(self.heads)
81
82
            self._print_elapsed_time('get heads:')
83
84
            ## mark heads as dead or alive
85
            # mark all heads as dead
86
            self.head_mark = {}
87
            self.tips = {}
88
            for head in self.heads:
89
                self.head_mark[head] = 'dead'
90
            # give the list of live branches in repository or current branch
91
            # tip
0.9.28 by Aaron Bentley
Simplify code by letting find_branches handle standalone branches
92
            self._iter_branches_update_marks(repo, self.outf.encoding)
0.9.22 by Aaron Bentley
Improve heads performance
93
            self._print_elapsed_time('make head marks:')
94
95
            if tips:
96
                heads_tips = set(self.heads)
97
                heads_tips.update(set(self.tips.keys()))
98
                self.heads = list(heads_tips)
0.9.23 by Aaron Bentley
defer getting revisions until self.heads is finalized
99
            head_revisions = dict(zip(self.heads,
100
                                  repo.get_revisions(self.heads)))
0.9.22 by Aaron Bentley
Improve heads performance
101
102
            # sorting by date
103
            if by_date:
104
                dates = {}
105
                for head in self.heads:
106
                    rev = head_revisions[head]
107
                    timestamp = rev.timestamp
108
                    dates[timestamp] = head
109
                keys = dates.keys()
110
                keys.sort()
111
                keys.reverse()
112
                self.heads = []
113
                for k in keys:
114
                    self.heads.append(dates[k])
115
                self._print_elapsed_time('sort by date:')
116
117
118
            # show time
119
            indent = ' '*2
120
            show_timezone = 'original'
121
0.9.18 by Alexander Belchenko
Prepare to list tips of branches
122
            for head in self.heads:
0.9.22 by Aaron Bentley
Improve heads performance
123
124
                mark = self.head_mark[head]
125
                if not all:
126
                    if dead_only:
127
                        if mark != 'dead':
0.9.19 by Alexander Belchenko
Added new flag --tips to show tips (last revid) of all branches in repo
128
                            continue
0.9.22 by Aaron Bentley
Improve heads performance
129
                    else:
130
                        if mark != 'alive':
131
                            if not tips or mark != 'tip':
132
                                continue
133
134
                # tips
135
                if mark in ('alive', 'tip'):
136
                    t = self.tips[head]
137
                    if len(t) > 1:
138
                        print >>to_file, 'TIP of branches:',
139
                        print >>to_file, '[', ', '.join(t), ']'
140
                    else:
141
                        print >>to_file, 'TIP of branch:', t[0]
142
143
                if mark in ('alive', 'dead'):
144
                    print >>to_file, 'HEAD:',
145
146
                print >>to_file, "revision-id:", head,
147
                if mark == 'dead':  print >>to_file, '(dead)'
148
                else:               print >>to_file
149
150
                rev = head_revisions[head]
151
                # borrowed from LongLogFormatter
152
                print >>to_file,  indent+'committer:', rev.committer
153
                try:
154
                    print >>to_file, indent+'branch nick: %s' % \
155
                        rev.properties['branch-nick']
156
                except KeyError:
157
                    pass
158
                date_str = format_date(rev.timestamp,
159
                                       rev.timezone or 0,
160
                                       show_timezone)
161
                print >>to_file,  indent+'timestamp: %s' % date_str
162
163
                print >>to_file,  indent+'message:'
164
                if not rev.message:
165
                    print >>to_file,  indent+'  (no message)'
0.9.19 by Alexander Belchenko
Added new flag --tips to show tips (last revid) of all branches in repo
166
                else:
0.9.22 by Aaron Bentley
Improve heads performance
167
                    message = rev.message.rstrip('\r\n')
168
                    for l in message.split('\n'):
169
                        print >>to_file,  indent+'  ' + l
170
                self._print_elapsed_time('print head:')
171
                print
172
173
            if not self.heads:
174
                print >>to_file, 'No heads found'
175
                return 1
176
        finally:
177
            repo.unlock()
0.9.14 by Alexander Belchenko
bzrtool's iter_branches is too slow. Added --debug-time feature show this fact
178
0.9.27 by Aaron Bentley
Support remote locations
179
    def _iter_branches_update_marks(self, repo, encoding):
0.9.26 by Aaron Bentley
Update to use new find_branches API
180
        for b in repo.find_branches(using=True):
0.9.17 by Alexander Belchenko
Restored support for running from standalone branch or not from root of shared repo
181
            last_revid = b.last_revision()
0.9.18 by Alexander Belchenko
Prepare to list tips of branches
182
            if last_revid in self.heads:
183
                self.head_mark[last_revid] = 'alive'
184
            else:
185
                self.head_mark[last_revid] = 'tip'
0.9.27 by Aaron Bentley
Support remote locations
186
            escaped = unescape_for_display(b.base, encoding)
187
            self.tips.setdefault(last_revid, []).append(escaped)
0.9.17 by Alexander Belchenko
Restored support for running from standalone branch or not from root of shared repo
188
0.9.14 by Alexander Belchenko
bzrtool's iter_branches is too slow. Added --debug-time feature show this fact
189
    def _init_elapsed_time(self, debug_time=False):
190
        self.debug_time = debug_time
191
        if debug_time:
192
            self._time = time.time()
193
194
    def _print_elapsed_time(self, msg):
195
        if self.debug_time:
196
            last_time = time.time()
197
            print msg, last_time - self._time
198
            self._time = last_time
0.9.1 by Alexander Belchenko
first version of heads command. thanks to Robert Collins for algorithm
199
#/class cmd_heads