154
155
return KnitContent(self._lines[:])
158
def get_line_delta_blocks(knit_delta, source, target):
159
"""Extract SequenceMatcher.get_matching_blocks() from a knit delta"""
160
target_len = len(target)
163
for s_begin, s_end, t_len, new_text in knit_delta:
164
true_n = s_begin - s_pos
167
# knit deltas do not provide reliable info about whether the
168
# last line of a file matches, due to eol handling.
169
if source[s_pos + n -1] != target[t_pos + n -1]:
172
yield s_pos, t_pos, n
173
t_pos += t_len + true_n
175
n = target_len - t_pos
177
if source[s_pos + n -1] != target[t_pos + n -1]:
180
yield s_pos, t_pos, n
181
yield s_pos + (target_len - t_pos), target_len, 0
157
184
class _KnitFactory(object):
158
185
"""Base factory for creating content objects."""
523
550
current_values[3],
553
def _extract_blocks(self, version_id, source, target):
554
if self._index.get_method(version_id) != 'line-delta':
556
parent, sha1, noeol, delta = self.get_delta(version_id)
557
return KnitContent.get_line_delta_blocks(delta, source, target)
526
559
def get_delta(self, version_id):
527
560
"""Get a delta for constructing version from some other version."""
528
561
version_id = osutils.safe_revision_id(version_id)
558
591
return dict(graph_items)
560
593
def get_sha1(self, version_id):
594
return self.get_sha1s([version_id])[0]
596
def get_sha1s(self, version_ids):
561
597
"""See VersionedFile.get_sha1()."""
562
version_id = osutils.safe_revision_id(version_id)
563
record_map = self._get_record_map([version_id])
564
method, content, digest, next = record_map[version_id]
598
version_ids = [osutils.safe_revision_id(v) for v in version_ids]
599
record_map = self._get_record_map(version_ids)
600
# record entry 2 is the 'digest'.
601
return [record_map[v][2] for v in version_ids]
568
604
def get_suffixes():
816
852
text_map, content_map = self._get_content_maps(version_ids)
817
853
return [text_map[v] for v in version_ids]
855
_get_lf_split_line_list = get_line_list
819
857
def _get_content_maps(self, version_ids):
820
858
"""Produce maps of text and KnitContents
1000
1038
ver_a = osutils.safe_revision_id(ver_a)
1001
1039
ver_b = osutils.safe_revision_id(ver_b)
1002
1040
ancestors_b = set(self.get_ancestry(ver_b, topo_sorted=False))
1003
def status_a(revision, text):
1004
if revision in ancestors_b:
1005
return 'killed-b', text
1007
return 'new-a', text
1009
1042
ancestors_a = set(self.get_ancestry(ver_a, topo_sorted=False))
1010
def status_b(revision, text):
1011
if revision in ancestors_a:
1012
return 'killed-a', text
1014
return 'new-b', text
1016
1043
annotated_a = self.annotate(ver_a)
1017
1044
annotated_b = self.annotate(ver_b)
1018
plain_a = [t for (a, t) in annotated_a]
1019
plain_b = [t for (a, t) in annotated_b]
1020
blocks = KnitSequenceMatcher(None, plain_a, plain_b).get_matching_blocks()
1023
for ai, bi, l in blocks:
1024
# process all mismatched sections
1025
# (last mismatched section is handled because blocks always
1026
# includes a 0-length last block)
1027
for revision, text in annotated_a[a_cur:ai]:
1028
yield status_a(revision, text)
1029
for revision, text in annotated_b[b_cur:bi]:
1030
yield status_b(revision, text)
1032
# and now the matched section
1035
for text_a, text_b in zip(plain_a[ai:a_cur], plain_b[bi:b_cur]):
1036
assert text_a == text_b
1037
yield "unchanged", text_a
1045
return merge._plan_annotate_merge(annotated_a, annotated_b,
1046
ancestors_a, ancestors_b)
1040
1049
class _KnitComponentFile(object):