86
69
def show_log(branch,
71
show_timezone='original',
93
75
"""Write out human-readable log of commits to this branch.
96
LogFormatter object to show the output.
99
78
If true, list only the commits affecting the specified
100
79
file, rather than all commits.
82
'original' (committer's timezone),
83
'utc' (universal time), or
84
'local' (local user's timezone)
103
87
If true show added/changed/deleted/renamed files.
106
'reverse' (default) is latest to earliest;
107
'forward' is earliest to latest.
110
If not None, only show revisions >= start_revision
113
If not None, only show revisions <= end_revision
115
from bzrlib.osutils import format_date
116
from bzrlib.errors import BzrCheckError
117
from bzrlib.textui import show_status
119
from warnings import warn
121
if not isinstance(lf, LogFormatter):
122
warn("not a LogFormatter instance: %r" % lf)
125
mutter('get log for file_id %r' % specific_fileid)
127
which_revs = branch.enum_history(direction)
128
which_revs = [x for x in which_revs if (
129
(start_revision is None or x[0] >= start_revision)
130
and (end_revision is None or x[0] <= end_revision))]
132
if not (verbose or specific_fileid):
133
# no need to know what changed between revisions
134
with_deltas = deltas_for_log_dummy(branch, which_revs)
135
elif direction == 'reverse':
136
with_deltas = deltas_for_log_reverse(branch, which_revs)
138
with_deltas = deltas_for_log_forward(branch, which_revs)
140
for revno, rev, delta in with_deltas:
142
if not delta.touches_file_id(specific_fileid):
146
# although we calculated it, throw it away without display
149
lf.show(revno, rev, delta)
153
def deltas_for_log_dummy(branch, which_revs):
154
for revno, revision_id in which_revs:
155
yield revno, branch.get_revision(revision_id), None
158
def deltas_for_log_reverse(branch, which_revs):
159
"""Compute deltas for display in reverse log.
161
Given a sequence of (revno, revision_id) pairs, return
164
The delta is from the given revision to the next one in the
165
sequence, which makes sense if the log is being displayed from
168
from tree import EmptyTree
169
from diff import compare_trees
171
last_revno = last_revision_id = last_tree = None
172
for revno, revision_id in which_revs:
173
this_tree = branch.revision_tree(revision_id)
174
this_revision = branch.get_revision(revision_id)
177
yield last_revno, last_revision, compare_trees(this_tree, last_tree, False)
180
last_revision = this_revision
181
last_tree = this_tree
185
this_tree = EmptyTree()
187
this_revno = last_revno - 1
188
this_revision_id = branch.revision_history()[this_revno]
189
this_tree = branch.revision_tree(this_revision_id)
190
yield last_revno, last_revision, compare_trees(this_tree, last_tree, False)
193
def deltas_for_log_forward(branch, which_revs):
194
"""Compute deltas for display in forward log.
196
Given a sequence of (revno, revision_id) pairs, return
199
The delta is from the given revision to the next one in the
200
sequence, which makes sense if the log is being displayed from
203
from tree import EmptyTree
204
from diff import compare_trees
206
last_revno = last_revision_id = last_tree = None
207
for revno, revision_id in which_revs:
208
this_tree = branch.revision_tree(revision_id)
209
this_revision = branch.get_revision(revision_id)
213
last_tree = EmptyTree()
215
last_revno = revno - 1
216
last_revision_id = branch.revision_history()[last_revno]
217
last_tree = branch.revision_tree(last_revision_id)
219
yield revno, this_revision, compare_trees(last_tree, this_tree, False)
222
last_revision = this_revision
223
last_tree = this_tree
226
class LogFormatter(object):
227
"""Abstract class to display log messages."""
228
def __init__(self, to_file, show_ids=False, show_timezone=False):
229
self.to_file = to_file
230
self.show_ids = show_ids
231
self.show_timezone = show_timezone
238
class LongLogFormatter(LogFormatter):
239
def show(self, revno, rev, delta):
240
from osutils import format_date
242
to_file = self.to_file
90
If true, show revision and file ids.
93
File to send log to; by default stdout.
95
from osutils import format_date
96
from errors import BzrCheckError
97
from diff import compare_inventories
98
from textui import show_status
99
from inventory import Inventory
106
file_id = branch.read_working_inventory().path2id(filename)
108
for revno, revid, why in find_touching_revisions(branch, file_id):
112
for i, revid in enumerate(branch.revision_history()):
115
branch._need_readlock()
118
prev_inv = Inventory()
119
for revno, revision_id in which_revs():
244
120
print >>to_file, '-' * 60
245
121
print >>to_file, 'revno:', revno
247
print >>to_file, 'revision-id:', rev.revision_id
122
rev = branch.get_revision(revision_id)
124
print >>to_file, 'revision-id:', revision_id
248
125
print >>to_file, 'committer:', rev.committer
249
126
print >>to_file, 'timestamp: %s' % (format_date(rev.timestamp, rev.timezone or 0,
129
if revision_id != rev.revision_id:
130
raise BzrCheckError("retrieved wrong revision: %r"
131
% (revision_id, rev.revision_id))
252
133
print >>to_file, 'message:'
253
134
if not rev.message:
256
137
for l in rev.message.split('\n'):
257
138
print >>to_file, ' ' + l
260
delta.show(to_file, self.show_ids)
264
class ShortLogFormatter(LogFormatter):
265
def show(self, revno, rev, delta):
266
from bzrlib.osutils import format_date
268
to_file = self.to_file
270
print >>to_file, "%5d %s\t%s" % (revno, rev.committer,
271
format_date(rev.timestamp, rev.timezone or 0,
274
print >>to_file, ' revision-id:', rev.revision_id
276
print >>to_file, ' (no message)'
278
for l in rev.message.split('\n'):
279
print >>to_file, ' ' + l
282
delta.show(to_file, self.show_ids)
287
FORMATTERS = {'long': LongLogFormatter,
288
'short': ShortLogFormatter,
292
def log_formatter(name, *args, **kwargs):
293
from bzrlib.errors import BzrCommandError
296
return FORMATTERS[name](*args, **kwargs)
298
raise BzrCommandError("unknown log formatter: %r" % name)
140
# Don't show a list of changed files if we were asked about
143
if verbose and not filename:
144
this_inv = branch.get_inventory(rev.inventory_id)
145
delta = compare_inventories(prev_inv, this_inv)
148
print >>to_file, 'removed files:'
149
for path, fid in delta.removed:
151
print >>to_file, ' %-30s %s' % (path, fid)
153
print >>to_file, ' ', path
155
print >>to_file, 'added files:'
156
for path, fid in delta.added:
158
print >>to_file, ' %-30s %s' % (path, fid)
160
print >>to_file, ' ' + path
162
print >>to_file, 'renamed files:'
163
for oldpath, newpath, fid in delta.renamed:
165
print >>to_file, ' %s => %s %s' % (oldpath, newpath, fid)
167
print >>to_file, ' %s => %s' % (oldpath, newpath)
169
print >>to_file, 'modified files:'
170
for path, fid in delta.modified:
172
print >>to_file, ' %-30s %s' % (path, fid)
174
print >>to_file, ' ' + path
178
precursor = revision_id