~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to heads.py

  • Committer: Aaron Bentley
  • Date: 2005-11-10 20:15:27 UTC
  • Revision ID: aaron.bentley@utoronto.ca-20051110201527-8caa84ae529a1871
Added Daniel Silverstone to credits

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Written by Alexander Belchenko
2
 
# based on Robert Collins code
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
17
 
 
18
 
"""Show all 'heads' in a repository"""
19
 
 
20
 
 
21
 
import os
22
 
import time
23
 
 
24
 
import bzrlib
25
 
from bzrlib.commands import Command, display_command, register_command
26
 
from bzrlib import errors
27
 
from bzrlib.option import Option
28
 
from bzrlib.urlutils import unescape_for_display
29
 
 
30
 
 
31
 
class cmd_heads(Command):
32
 
    """Show all revisions in a repository not having descendants.
33
 
    """
34
 
    takes_options = [Option('by-date',
35
 
                     help='Sort heads by date (descending).'),
36
 
                     Option('all', help='Show all heads (dead and alive).'),
37
 
                     Option('dead-only', help='Show only dead heads.'),
38
 
                     Option('tips', help='Show tips of all branches.'),
39
 
                     Option('debug-time',
40
 
                     help='Enable debug print of operations times.'),
41
 
                    ]
42
 
 
43
 
    encoding_type = "replace"
44
 
    takes_args = ['location?']
45
 
 
46
 
    @display_command
47
 
    def run(self, by_date=False, all=False, dead_only=False, tips=False,
48
 
            debug_time=False, location='.'):
49
 
        import bzrlib.branch
50
 
        from bzrlib.osutils import format_date
51
 
        import bzrlib.repository
52
 
 
53
 
        self._init_elapsed_time(debug_time)
54
 
 
55
 
        to_file = self.outf
56
 
 
57
 
        branch = None
58
 
        try:
59
 
            branch = bzrlib.branch.Branch.open_containing(location)[0]
60
 
            repo = branch.repository
61
 
        except errors.NotBranchError:
62
 
            try:
63
 
                repo = bzrlib.repository.Repository.open(location)
64
 
            except errors.NotBranchError:
65
 
                print >>to_file, \
66
 
                      ("You need to run this command "
67
 
                       "either from the root of a shared repository,\n"
68
 
                       "or from a branch.")
69
 
                return 3
70
 
        repo.lock_read()
71
 
        try:
72
 
            possible_heads = set(repo.all_revision_ids())
73
 
            g = repo.get_graph().get_parent_map(possible_heads)
74
 
            not_heads = set()
75
 
            for parents in g.values():
76
 
                not_heads.update(set(parents))
77
 
 
78
 
            self.heads = possible_heads.difference(not_heads)
79
 
 
80
 
            # TODO: use different sorting schemes instead of alphabetical sort
81
 
            self.heads = list(self.heads)
82
 
 
83
 
            self._print_elapsed_time('get heads:')
84
 
 
85
 
            ## mark heads as dead or alive
86
 
            # mark all heads as dead
87
 
            self.head_mark = {}
88
 
            self.tips = {}
89
 
            for head in self.heads:
90
 
                self.head_mark[head] = 'dead'
91
 
            # give the list of live branches in repository or current branch
92
 
            # tip
93
 
            self._iter_branches_update_marks(repo, self.outf.encoding)
94
 
            self._print_elapsed_time('make head marks:')
95
 
 
96
 
            if tips:
97
 
                heads_tips = set(self.heads)
98
 
                heads_tips.update(set(self.tips.keys()))
99
 
                self.heads = list(heads_tips)
100
 
            head_revisions = dict(zip(self.heads,
101
 
                                  repo.get_revisions(self.heads)))
102
 
 
103
 
            # sorting by date
104
 
            if by_date:
105
 
                dates = {}
106
 
                for head in self.heads:
107
 
                    rev = head_revisions[head]
108
 
                    timestamp = rev.timestamp
109
 
                    dates[timestamp] = head
110
 
                keys = dates.keys()
111
 
                keys.sort()
112
 
                keys.reverse()
113
 
                self.heads = []
114
 
                for k in keys:
115
 
                    self.heads.append(dates[k])
116
 
                self._print_elapsed_time('sort by date:')
117
 
 
118
 
 
119
 
            # show time
120
 
            indent = ' '*2
121
 
            show_timezone = 'original'
122
 
 
123
 
            for head in self.heads:
124
 
 
125
 
                mark = self.head_mark[head]
126
 
                if not all:
127
 
                    if dead_only:
128
 
                        if mark != 'dead':
129
 
                            continue
130
 
                    else:
131
 
                        if mark != 'alive':
132
 
                            if not tips or mark != 'tip':
133
 
                                continue
134
 
 
135
 
                # tips
136
 
                if mark in ('alive', 'tip'):
137
 
                    t = self.tips[head]
138
 
                    if len(t) > 1:
139
 
                        print >>to_file, 'TIP of branches:',
140
 
                        print >>to_file, '[', ', '.join(t), ']'
141
 
                    else:
142
 
                        print >>to_file, 'TIP of branch:', t[0]
143
 
 
144
 
                if mark in ('alive', 'dead'):
145
 
                    print >>to_file, 'HEAD:',
146
 
 
147
 
                print >>to_file, "revision-id:", head,
148
 
                if mark == 'dead':  print >>to_file, '(dead)'
149
 
                else:               print >>to_file
150
 
 
151
 
                rev = head_revisions[head]
152
 
                # borrowed from LongLogFormatter
153
 
                print >>to_file,  indent+'committer:', rev.committer
154
 
                try:
155
 
                    print >>to_file, indent+'branch nick: %s' % \
156
 
                        rev.properties['branch-nick']
157
 
                except KeyError:
158
 
                    pass
159
 
                date_str = format_date(rev.timestamp,
160
 
                                       rev.timezone or 0,
161
 
                                       show_timezone)
162
 
                print >>to_file,  indent+'timestamp: %s' % date_str
163
 
 
164
 
                print >>to_file,  indent+'message:'
165
 
                if not rev.message:
166
 
                    print >>to_file,  indent+'  (no message)'
167
 
                else:
168
 
                    message = rev.message.rstrip('\r\n')
169
 
                    for l in message.split('\n'):
170
 
                        print >>to_file,  indent+'  ' + l
171
 
                self._print_elapsed_time('print head:')
172
 
                print
173
 
 
174
 
            if not self.heads:
175
 
                print >>to_file, 'No heads found'
176
 
                return 1
177
 
        finally:
178
 
            repo.unlock()
179
 
 
180
 
    def _iter_branches_update_marks(self, repo, encoding):
181
 
        for b in repo.find_branches(using=True):
182
 
            last_revid = b.last_revision()
183
 
            if last_revid in self.heads:
184
 
                self.head_mark[last_revid] = 'alive'
185
 
            else:
186
 
                self.head_mark[last_revid] = 'tip'
187
 
            escaped = unescape_for_display(b.base, encoding)
188
 
            self.tips.setdefault(last_revid, []).append(escaped)
189
 
 
190
 
    def _init_elapsed_time(self, debug_time=False):
191
 
        self.debug_time = debug_time
192
 
        if debug_time:
193
 
            self._time = time.time()
194
 
 
195
 
    def _print_elapsed_time(self, msg):
196
 
        if self.debug_time:
197
 
            last_time = time.time()
198
 
            print msg, last_time - self._time
199
 
            self._time = last_time
200
 
#/class cmd_heads