~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Robert Collins
  • Date: 2007-07-25 00:52:21 UTC
  • mfrom: (2650 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2651.
  • Revision ID: robertc@robertcollins.net-20070725005221-0ysm6il5mqnme3wz
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
76
76
    osutils,
77
77
    patiencediff,
78
78
    progress,
 
79
    merge,
79
80
    ui,
80
81
    )
81
82
from bzrlib.errors import (
153
154
    def copy(self):
154
155
        return KnitContent(self._lines[:])
155
156
 
 
157
    @staticmethod
 
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)
 
161
        s_pos = 0
 
162
        t_pos = 0
 
163
        for s_begin, s_end, t_len, new_text in knit_delta:
 
164
            true_n = s_begin - s_pos
 
165
            n = true_n
 
166
            if n > 0:
 
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]:
 
170
                    n-=1
 
171
                if n > 0:
 
172
                    yield s_pos, t_pos, n
 
173
            t_pos += t_len + true_n
 
174
            s_pos = s_end
 
175
        n = target_len - t_pos
 
176
        if n > 0:
 
177
            if source[s_pos + n -1] != target[t_pos + n -1]:
 
178
                n-=1
 
179
            if n > 0:
 
180
                yield s_pos, t_pos, n
 
181
        yield s_pos + (target_len - t_pos), target_len, 0
 
182
 
156
183
 
157
184
class _KnitFactory(object):
158
185
    """Base factory for creating content objects."""
523
550
                                current_values[3],
524
551
                                new_parents)
525
552
 
 
553
    def _extract_blocks(self, version_id, source, target):
 
554
        if self._index.get_method(version_id) != 'line-delta':
 
555
            return None
 
556
        parent, sha1, noeol, delta = self.get_delta(version_id)
 
557
        return KnitContent.get_line_delta_blocks(delta, source, target)
 
558
 
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)
559
592
 
560
593
    def get_sha1(self, version_id):
 
594
        return self.get_sha1s([version_id])[0]
 
595
 
 
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]
565
 
        return digest 
 
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]
566
602
 
567
603
    @staticmethod
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]
818
854
 
 
855
    _get_lf_split_line_list = get_line_list
 
856
 
819
857
    def _get_content_maps(self, version_ids):
820
858
        """Produce maps of text and KnitContents
821
859
        
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
1006
 
            else:
1007
 
                return 'new-a', text
1008
1041
        
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
1013
 
            else:
1014
 
                return 'new-b', text
1015
 
 
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()
1021
 
        a_cur = 0
1022
 
        b_cur = 0
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)
1031
 
 
1032
 
            # and now the matched section
1033
 
            a_cur = ai + l
1034
 
            b_cur = bi + l
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)
1038
1047
 
1039
1048
 
1040
1049
class _KnitComponentFile(object):