~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to heads.py

  • Committer: Michael Ellerman
  • Date: 2005-11-29 07:12:26 UTC
  • mto: (0.3.1 shelf-dev) (325.1.2 bzrtools)
  • mto: This revision was merged to the branch mainline in revision 334.
  • Revision ID: michael@ellerman.id.au-20051129071226-a04b3f827880025d
Unshelve --pick was broken, because we deleted the whole patch, even when only
part of it was unshelved. So now if we unshelve part of a patch, the patch is
replaced with a new patch that has just the unshelved parts. That's a long way
of saying it does what you'd expect.

Implementing this required changing HunkSelector to return both the selected,
and unselected hunks (ie. patches to shelve, and patches to keep).

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