1
# Copyright (C) 2005 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
"""Code to show logs of changes.
21
Various flavors of log can be produced:
23
* for one file, or the whole tree, and (not done yet) for
24
files in a given directory
26
* in "verbose" mode with a description of what changed from one
29
* with file-ids and revision-ids shown
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
35
* (not yet) in XML format
40
def find_touching_revisions(branch, file_id):
41
"""Yield a description of revisions which affect the file_id.
43
Each returned element is (revno, revision_id, description)
45
This is the list of revisions where the file is either added,
46
modified, renamed or deleted.
48
TODO: Perhaps some way to limit this to only particular revisions,
49
or to traverse a non-mainline set of revisions?
54
for revision_id in branch.revision_history():
55
this_inv = branch.get_revision_inventory(revision_id)
56
if file_id in this_inv:
57
this_ie = this_inv[file_id]
58
this_path = this_inv.id2path(file_id)
60
this_ie = this_path = None
62
# now we know how it was last time, and how it is in this revision.
63
# are those two states effectively the same or not?
65
if not this_ie and not last_ie:
66
# not present in either
68
elif this_ie and not last_ie:
69
yield revno, revision_id, "added " + this_path
70
elif not this_ie and last_ie:
72
yield revno, revision_id, "deleted " + last_path
73
elif this_path != last_path:
74
yield revno, revision_id, ("renamed %s => %s" % (last_path, this_path))
75
elif (this_ie.text_size != last_ie.text_size
76
or this_ie.text_sha1 != last_ie.text_sha1):
77
yield revno, revision_id, "modified " + this_path
87
show_timezone='original',
92
"""Write out human-readable log of commits to this branch.
95
If true, list only the commits affecting the specified
96
file, rather than all commits.
99
'original' (committer's timezone),
100
'utc' (universal time), or
101
'local' (local user's timezone)
104
If true show added/changed/deleted/renamed files.
107
If true, show revision and file ids.
110
File to send log to; by default stdout.
113
'reverse' (default) is latest to earliest;
114
'forward' is earliest to latest.
116
from osutils import format_date
117
from errors import BzrCheckError
118
from diff import compare_trees
119
from textui import show_status
125
if specific_fileid or verbose:
126
raise NotImplementedError('sorry, option not implemented at the moment')
128
which_revs = branch.enum_history(direction)
130
for revno, revision_id in which_revs:
131
# TODO: if filename given, check if it's changed; if not
132
# changed, skip this one
134
# TODO: if verbose, get a list of changes; if we're running
135
# forward then the delta is as compared to the previous
136
# version, otherwise as compared to the *next* version to be
137
# enumerated; in both cases must treat 0 specially as the
140
rev = branch.get_revision(revision_id)
142
show_one_log(revno, rev, delta, show_ids, to_file, show_timezone)
148
from tree import EmptyTree
149
prev_tree = EmptyTree()
150
for revno, revision_id in which_revs:
151
precursor = revision_id
153
if revision_id != rev.revision_id:
154
raise BzrCheckError("retrieved wrong revision: %r"
155
% (revision_id, rev.revision_id))
158
this_tree = branch.revision_tree(revision_id)
159
delta = compare_trees(prev_tree, this_tree, want_unchanged=False)
160
prev_tree = this_tree
166
def show_one_log(revno, rev, delta, show_ids, to_file, show_timezone):
167
from osutils import format_date
169
print >>to_file, '-' * 60
170
print >>to_file, 'revno:', revno
172
print >>to_file, 'revision-id:', rev.revision_id
173
print >>to_file, 'committer:', rev.committer
174
print >>to_file, 'timestamp: %s' % (format_date(rev.timestamp, rev.timezone or 0,
177
print >>to_file, 'message:'
179
print >>to_file, ' (no message)'
181
for l in rev.message.split('\n'):
182
print >>to_file, ' ' + l
185
delta.show(to_file, show_ids)