99
99
def _annotate_file(branch, rev_id, file_id):
100
100
"""Yield the origins for each line of a file.
102
This includes detailed information, such as the committer name, and
102
This includes detailed information, such as the author name, and
103
103
date string for the commit, rather than just the revision id.
105
105
revision_id_to_revno = branch.get_revision_id_to_revno_map()
129
129
time.gmtime(rev.timestamp + tz))
130
130
# a lazy way to get something like the email address
131
131
# TODO: Get real email address
132
author = rev.committer
132
author = rev.get_apparent_author()
134
134
author = extract_email_address(author)
135
135
except errors.NoEmailInUsername:
137
137
yield (revno_str, author, date_str, origin, text)
140
def reannotate(parents_lines, new_lines, new_revision_id):
140
def reannotate(parents_lines, new_lines, new_revision_id,
141
_left_matching_blocks=None):
141
142
"""Create a new annotated version from new lines and parent annotations.
143
144
:param parents_lines: List of annotated lines for all parents
144
145
:param new_lines: The un-annotated new lines
145
146
:param new_revision_id: The revision-id to associate with new lines
146
147
(will often be CURRENT_REVISION)
148
:param left_matching_blocks: a hint about which areas are common
149
between the text and its left-hand-parent. The format is
150
the SequenceMatcher.get_matching_blocks format.
148
if len(parents_lines) == 1:
149
for data in _reannotate(parents_lines[0], new_lines, new_revision_id):
152
if len(parents_lines) == 0:
153
for line in new_lines:
154
yield new_revision_id, line
155
elif len(parents_lines) == 1:
156
for data in _reannotate(parents_lines[0], new_lines, new_revision_id,
157
_left_matching_blocks):
152
reannotations = [list(_reannotate(p, new_lines, new_revision_id)) for
160
block_list = [_left_matching_blocks] + [None] * len(parents_lines)
161
reannotations = [list(_reannotate(p, new_lines, new_revision_id, b))
162
for p, b in zip(parents_lines, block_list)]
154
163
for annos in zip(*reannotations):
155
164
origins = set(a for a, l in annos)
156
165
line = annos[0][1]
162
171
yield new_revision_id, line
165
def _reannotate(parent_lines, new_lines, new_revision_id):
174
def _reannotate(parent_lines, new_lines, new_revision_id,
175
matching_blocks=None):
166
176
plain_parent_lines = [l for r, l in parent_lines]
167
177
matcher = patiencediff.PatienceSequenceMatcher(None, plain_parent_lines,
170
for i, j, n in matcher.get_matching_blocks():
180
if matching_blocks is None:
181
matching_blocks = matcher.get_matching_blocks()
182
for i, j, n in matching_blocks:
171
183
for line in new_lines[new_cur:j]:
172
184
yield new_revision_id, line
173
185
for data in parent_lines[i:i+n]: