57
59
to_file = sys.stdout
59
61
# Handle the show_ids case
62
annotations = _annotations(branch.repository, file_id, rev_id)
62
annotations = _annotations(branch.repository, file_id, rev_id)
63
max_origin_len = max(len(origin) for origin, text in annotations)
64
for origin, text in annotations:
65
if full or last_rev_id != origin:
69
to_file.write('%*s | %s' % (max_origin_len, this, text))
64
return _show_id_annotations(annotations, to_file, full)
73
66
# Calculate the lengths of the various columns
74
annotation = list(_annotate_file(branch, rev_id, file_id))
67
annotation = list(_expand_annotations(annotations, branch))
68
_print_annotations(annotation, verbose, to_file, full)
71
def annotate_file_tree(tree, file_id, to_file, verbose=False, full=False,
73
"""Annotate file_id in a tree.
75
The tree should already be read_locked() when annotate_file_tree is called.
77
:param tree: The tree to look for revision numbers and history from.
78
:param file_id: The file_id to annotate.
79
:param to_file: The file to output the annotation to.
80
:param verbose: Show all details rather than truncating to ensure
81
reasonable text width.
82
:param full: XXXX Not sure what this does.
83
:param show_ids: Show revision ids in the annotation output.
85
rev_id = tree.last_revision()
88
# Handle the show_ids case
89
annotations = list(tree.annotate_iter(file_id))
91
return _show_id_annotations(annotations, to_file, full)
93
# Create a virtual revision to represent the current tree state.
94
# Should get some more pending commit attributes, like pending tags,
96
current_rev = Revision(CURRENT_REVISION)
97
current_rev.parent_ids = tree.get_parent_ids()
98
current_rev.committer = tree.branch.get_config().username()
99
current_rev.message = "?"
100
current_rev.timestamp = round(time.time(), 3)
101
current_rev.timezone = osutils.local_time_offset()
102
annotation = list(_expand_annotations(annotations, tree.branch,
104
_print_annotations(annotation, verbose, to_file, full)
107
def _print_annotations(annotation, verbose, to_file, full):
108
"""Print annotations to to_file.
110
:param to_file: The file to output the annotation to.
111
:param verbose: Show all details rather than truncating to ensure
112
reasonable text width.
113
:param full: XXXX Not sure what this does.
75
115
if len(annotation) == 0:
76
116
max_origin_len = max_revno_len = max_revid_len = 0
153
def _show_id_annotations(annotations, to_file, full):
155
max_origin_len = max(len(origin) for origin, text in annotations)
156
for origin, text in annotations:
157
if full or last_rev_id != origin:
161
to_file.write('%*s | %s' % (max_origin_len, this, text))
113
166
def _annotations(repo, file_id, rev_id):
114
167
"""Return the list of (origin_revision_id, line_text) for a revision of a file in a repository."""
115
168
annotations = repo.texts.annotate((file_id, rev_id))
117
170
return [(key[-1], line) for (key, line) in annotations]
120
def _annotate_file(branch, rev_id, file_id):
121
"""Yield the origins for each line of a file.
123
This includes detailed information, such as the author name, and
124
date string for the commit, rather than just the revision id.
173
def _expand_annotations(annotations, branch, current_rev=None):
174
"""Expand a a files annotations into command line UI ready tuples.
176
Each tuple includes detailed information, such as the author name, and date
177
string for the commit, rather than just the revision id.
179
:param annotations: The annotations to expand.
180
:param revision_id_to_revno: A map from id to revision numbers.
181
:param branch: A locked branch to query for revision details.
126
revision_id_to_revno = branch.get_revision_id_to_revno_map()
127
annotations = _annotations(branch.repository, file_id, rev_id)
183
repository = branch.repository
184
if current_rev is not None:
185
# This can probably become a function on MutableTree, get_revno_map there,
187
last_revision = current_rev.revision_id
188
# XXX: Partially Cloned from branch, uses the old_get_graph, eep.
189
graph = repository.get_graph()
190
revision_graph = dict(((key, value) for key, value in
191
graph.iter_ancestry(current_rev.parent_ids) if value is not None))
192
revision_graph = _strip_NULL_ghosts(revision_graph)
193
revision_graph[last_revision] = current_rev.parent_ids
194
merge_sorted_revisions = tsort.merge_sort(
199
revision_id_to_revno = dict((rev_id, revno)
200
for seq_num, rev_id, depth, revno, end_of_merge in
201
merge_sorted_revisions)
203
revision_id_to_revno = branch.get_revision_id_to_revno_map()
128
204
last_origin = None
129
205
revision_ids = set(o for o, t in annotations)
207
if CURRENT_REVISION in revision_ids:
208
revision_id_to_revno[CURRENT_REVISION] = (
209
"%d?" % (branch.revno() + 1),)
210
revisions[CURRENT_REVISION] = current_rev
130
211
revision_ids = [o for o in revision_ids if
131
branch.repository.has_revision(o)]
132
revisions = dict((r.revision_id, r) for r in
133
branch.repository.get_revisions(revision_ids))
212
repository.has_revision(o)]
213
revisions.update((r.revision_id, r) for r in
214
repository.get_revisions(revision_ids))
134
215
for origin, text in annotations:
135
216
text = text.rstrip('\r\n')
136
217
if origin == last_origin: