~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/log.py

  • Committer: Aaron Bentley
  • Date: 2005-07-29 17:19:16 UTC
  • mto: (1092.1.41) (1185.3.4) (974.1.47)
  • mto: This revision was merged to the branch mainline in revision 1020.
  • Revision ID: abentley@panoramicfeedback.com-20050729171916-322fd81b451d2e3e
Added merge-type parameter to merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
* with file-ids and revision-ids shown
30
30
 
31
 
Logs are actually written out through an abstract LogFormatter
32
 
interface, which allows for different preferred formats.  Plugins can
33
 
register formats too.
34
 
 
35
 
Logs can be produced in either forward (oldest->newest) or reverse
36
 
(newest->oldest) order.
37
 
 
38
 
Logs can be filtered to show only revisions matching a particular
39
 
search string, or within a particular range of revisions.  The range
40
 
can be given as date/times, which are reduced to revisions before
41
 
calling in here.
42
 
 
43
 
In verbose mode we show a summary of what changed in each particular
44
 
revision.  Note that this is the delta for changes in that revision
45
 
relative to its mainline parent, not the delta relative to the last
46
 
logged revision.  So for example if you ask for a verbose log of
47
 
changes touching hello.c you will get a list of those revisions also
48
 
listing other things that were changed in the same revision, but not
49
 
all the changes since the previous revision that touched hello.c.
 
31
* from last to first or (not anymore) from first to last;
 
32
  the default is "reversed" because it shows the likely most
 
33
  relevant and interesting information first
 
34
 
 
35
* (not yet) in XML format
50
36
"""
51
37
 
52
38
 
53
 
from bzrlib.tree import EmptyTree
54
 
from bzrlib.delta import compare_trees
55
 
from bzrlib.trace import mutter
56
 
 
 
39
from trace import mutter
57
40
 
58
41
def find_touching_revisions(branch, file_id):
59
42
    """Yield a description of revisions which affect the file_id.
100
83
 
101
84
 
102
85
 
103
 
def _enumerate_history(branch):
104
 
    rh = []
105
 
    revno = 1
106
 
    for rev_id in branch.revision_history():
107
 
        rh.append((revno, rev_id))
108
 
        revno += 1
109
 
    return rh
110
 
 
111
 
 
112
86
def show_log(branch,
113
87
             lf,
114
88
             specific_fileid=None,
157
131
    else:
158
132
        searchRE = None
159
133
 
160
 
    which_revs = _enumerate_history(branch)
161
 
    
162
 
    if start_revision is None:
163
 
        start_revision = 1
164
 
    else:
165
 
        branch.check_real_revno(start_revision)
166
 
    
167
 
    if end_revision is None:
168
 
        end_revision = len(which_revs)
169
 
    else:
170
 
        branch.check_real_revno(end_revision)
171
 
 
172
 
    # list indexes are 0-based; revisions are 1-based
173
 
    cut_revs = which_revs[(start_revision-1):(end_revision)]
174
 
 
175
 
    if direction == 'reverse':
176
 
        cut_revs.reverse()
177
 
    elif direction == 'forward':
178
 
        pass
179
 
    else:
180
 
        raise ValueError('invalid direction %r' % direction)
181
 
 
182
 
    for revno, rev_id in cut_revs:
183
 
        if verbose or specific_fileid:
184
 
            delta = branch.get_revision_delta(revno)
185
 
            
 
134
    which_revs = branch.enum_history(direction)
 
135
    which_revs = [x for x in which_revs if (
 
136
            (start_revision is None or x[0] >= start_revision)
 
137
            and (end_revision is None or x[0] <= end_revision))]
 
138
 
 
139
    if not (verbose or specific_fileid):
 
140
        # no need to know what changed between revisions
 
141
        with_deltas = deltas_for_log_dummy(branch, which_revs)
 
142
    elif direction == 'reverse':
 
143
        with_deltas = deltas_for_log_reverse(branch, which_revs)
 
144
    else:        
 
145
        with_deltas = deltas_for_log_forward(branch, which_revs)
 
146
 
 
147
    for revno, rev, delta in with_deltas:
186
148
        if specific_fileid:
187
149
            if not delta.touches_file_id(specific_fileid):
188
150
                continue
191
153
            # although we calculated it, throw it away without display
192
154
            delta = None
193
155
 
194
 
        rev = branch.get_revision(rev_id)
195
 
 
196
 
        if searchRE:
197
 
            if not searchRE.search(rev.message):
198
 
                continue
199
 
 
200
 
        lf.show(revno, rev, delta)
 
156
        if searchRE is None or searchRE.search(rev.message):
 
157
            lf.show(revno, rev, delta)
201
158
 
202
159
 
203
160
 
204
161
def deltas_for_log_dummy(branch, which_revs):
205
 
    """Return all the revisions without intermediate deltas.
206
 
 
207
 
    Useful for log commands that won't need the delta information.
208
 
    """
209
 
    
210
162
    for revno, revision_id in which_revs:
211
163
        yield revno, branch.get_revision(revision_id), None
212
164
 
213
165
 
214
166
def deltas_for_log_reverse(branch, which_revs):
215
 
    """Compute deltas for display in latest-to-earliest order.
216
 
 
217
 
    branch
218
 
        Branch to traverse
219
 
 
220
 
    which_revs
221
 
        Sequence of (revno, revision_id) for the subset of history to examine
222
 
 
223
 
    returns 
224
 
        Sequence of (revno, rev, delta)
 
167
    """Compute deltas for display in reverse log.
 
168
 
 
169
    Given a sequence of (revno, revision_id) pairs, return
 
170
    (revno, rev, delta).
225
171
 
226
172
    The delta is from the given revision to the next one in the
227
173
    sequence, which makes sense if the log is being displayed from
228
174
    newest to oldest.
229
175
    """
 
176
    from tree import EmptyTree
 
177
    from diff import compare_trees
 
178
    
230
179
    last_revno = last_revision_id = last_tree = None
231
180
    for revno, revision_id in which_revs:
232
181
        this_tree = branch.revision_tree(revision_id)
261
210
    sequence, which makes sense if the log is being displayed from
262
211
    newest to oldest.
263
212
    """
 
213
    from tree import EmptyTree
 
214
    from diff import compare_trees
 
215
 
264
216
    last_revno = last_revision_id = last_tree = None
265
217
    prev_tree = EmptyTree(branch.get_root_id())
266
218
 
285
237
 
286
238
class LogFormatter(object):
287
239
    """Abstract class to display log messages."""
288
 
    def __init__(self, to_file, show_ids=False, show_timezone='original'):
 
240
    def __init__(self, to_file, show_ids=False, show_timezone=False):
289
241
        self.to_file = to_file
290
242
        self.show_ids = show_ids
291
243
        self.show_timezone = show_timezone
292
 
 
293
 
 
294
 
    def show(self, revno, rev, delta):
295
 
        raise NotImplementedError('not implemented in abstract base')
296
244
        
297
245
 
298
246
 
309
257
        print >>to_file,  'revno:', revno
310
258
        if self.show_ids:
311
259
            print >>to_file,  'revision-id:', rev.revision_id
312
 
 
313
 
            for parent in rev.parents:
314
 
                print >>to_file, 'parent:', parent.revision_id
315
 
            
316
260
        print >>to_file,  'committer:', rev.committer
317
 
 
318
 
        date_str = format_date(rev.timestamp,
319
 
                               rev.timezone or 0,
320
 
                               self.show_timezone)
321
 
        print >>to_file,  'timestamp: %s' % date_str
 
261
        print >>to_file,  'timestamp: %s' % (format_date(rev.timestamp, rev.timezone or 0,
 
262
                                             self.show_timezone))
322
263
 
323
264
        print >>to_file,  'message:'
324
265
        if not rev.message:
349
290
            for l in rev.message.split('\n'):
350
291
                print >>to_file,  '      ' + l
351
292
 
352
 
        # TODO: Why not show the modified files in a shorter form as
353
 
        # well? rewrap them single lines of appropriate length
354
293
        if delta != None:
355
294
            delta.show(to_file, self.show_ids)
356
295
        print
369
308
        return FORMATTERS[name](*args, **kwargs)
370
309
    except IndexError:
371
310
        raise BzrCommandError("unknown log formatter: %r" % name)
372
 
 
373
 
def show_one_log(revno, rev, delta, verbose, to_file, show_timezone):
374
 
    # deprecated; for compatability
375
 
    lf = LongLogFormatter(to_file=to_file, show_timezone=show_timezone)
376
 
    lf.show(revno, rev, delta)