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
20
def find_touching_revisions(branch, file_id):
21
"""Yield a description of revisions which affect the file_id.
23
Each returned element is (revno, revision_id, description)
25
This is the list of revisions where the file is either added,
26
modified, renamed or deleted.
28
Revisions are returned in chronological order.
30
TODO: Perhaps some way to limit this to only particular revisions,
31
or to traverse a non-branch set of revisions?
36
for revision_id in branch.revision_history():
37
this_inv = branch.get_revision_inventory(revision_id)
38
if file_id in this_inv:
39
this_ie = this_inv[file_id]
40
this_path = this_inv.id2path(file_id)
42
this_ie = this_path = None
44
# now we know how it was last time, and how it is in this revision.
45
# are those two states effectively the same or not?
47
if not this_ie and not last_ie:
48
# not present in either
50
elif this_ie and not last_ie:
51
yield revno, revision_id, "added " + this_path
52
elif not this_ie and last_ie:
54
yield revno, revision_id, "deleted " + last_path
55
elif this_path != last_path:
56
yield revno, revision_id, ("renamed %s => %s" % (last_path, this_path))
57
elif (this_ie.text_size != last_ie.text_size
58
or this_ie.text_sha1 != last_ie.text_sha1):
59
yield revno, revision_id, "modified " + this_path
66
def show_log(branch, show_timezone='original', verbose=False,
69
"""Write out human-readable log of commits to this branch.
72
'original' (committer's timezone),
73
'utc' (universal time), or
74
'local' (local user's timezone)
77
If true show added/changed/deleted/renamed files.
80
If true, show revision and file ids.
83
File to send log to; by default stdout.
85
from osutils import format_date
86
from errors import BzrCheckError
87
from diff import diff_trees
88
from textui import show_status
94
branch._need_readlock()
97
for revision_id in branch.revision_history():
98
print >>to_file, '-' * 60
99
print >>to_file, 'revno:', revno
100
rev = branch.get_revision(revision_id)
102
print >>to_file, 'revision-id:', revision_id
103
print >>to_file, 'committer:', rev.committer
104
print >>to_file, 'timestamp: %s' % (format_date(rev.timestamp, rev.timezone or 0,
107
if revision_id != rev.revision_id:
108
raise BzrCheckError("retrieved wrong revision: %r"
109
% (revision_id, rev.revision_id))
111
## opportunistic consistency check, same as check_patch_chaining
112
if rev.precursor != precursor:
113
raise BzrCheckError("mismatched precursor!")
115
print >>to_file, 'message:'
117
print >>to_file, ' (no message)'
119
for l in rev.message.split('\n'):
120
print >>to_file, ' ' + l
122
if verbose and precursor:
123
# TODO: Group as added/deleted/renamed instead
124
# TODO: Show file ids
125
print >>to_file, 'changed files:'
126
tree = branch.revision_tree(revision_id)
127
prevtree = branch.revision_tree(precursor)
129
for file_state, fid, old_name, new_name, kind in \
130
diff_trees(prevtree, tree, ):
131
if file_state == 'A' or file_state == 'M':
132
show_status(file_state, kind, new_name)
133
elif file_state == 'D':
134
show_status(file_state, kind, old_name)
135
elif file_state == 'R':
136
show_status(file_state, kind,
137
old_name + ' => ' + new_name)
140
precursor = revision_id