/loggerhead/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/loggerhead/trunk

« back to all changes in this revision

Viewing changes to loggerhead/history.py

  • Committer: Michael Hudson
  • Date: 2009-02-18 00:56:51 UTC
  • mfrom: (269.1.8 clean-up-revision-view)
  • Revision ID: michael.hudson@canonical.com-20090218005651-0djjmxad3prwgui7
clean up the revision template and code a bit

Show diffs side-by-side

added added

removed removed

Lines of Context:
67
67
 
68
68
bzrlib.ui.ui_factory = ThreadSafeUIFactory()
69
69
 
70
 
 
71
 
def _process_side_by_side_buffers(line_list, delete_list, insert_list):
72
 
    while len(delete_list) < len(insert_list):
73
 
        delete_list.append((None, '', 'context'))
74
 
    while len(insert_list) < len(delete_list):
75
 
        insert_list.append((None, '', 'context'))
76
 
    while len(delete_list) > 0:
77
 
        d = delete_list.pop(0)
78
 
        i = insert_list.pop(0)
79
 
        line_list.append(util.Container(old_lineno=d[0], new_lineno=i[0],
80
 
                                        old_line=d[1], new_line=i[1],
81
 
                                        old_type=d[2], new_type=i[2]))
82
 
 
83
 
 
84
 
def _make_side_by_side(chunk_list):
85
 
    """
86
 
    turn a normal unified-style diff (post-processed by parse_delta) into a
87
 
    side-by-side diff structure.  the new structure is::
88
 
 
89
 
        chunks: list(
90
 
            diff: list(
91
 
                old_lineno: int,
92
 
                new_lineno: int,
93
 
                old_line: str,
94
 
                new_line: str,
95
 
                type: str('context' or 'changed'),
96
 
            )
97
 
        )
98
 
    """
99
 
    out_chunk_list = []
100
 
    for chunk in chunk_list:
101
 
        line_list = []
102
 
        wrap_char = '<wbr/>'
103
 
        delete_list, insert_list = [], []
104
 
        for line in chunk.diff:
105
 
            # Add <wbr/> every X characters so we can wrap properly
106
 
            wrap_line = re.findall(r'.{%d}|.+$' % 78, line.line)
107
 
            wrap_lines = [util.html_clean(_line) for _line in wrap_line]
108
 
            wrapped_line = wrap_char.join(wrap_lines)
109
 
 
110
 
            if line.type == 'context':
111
 
                if len(delete_list) or len(insert_list):
112
 
                    _process_side_by_side_buffers(line_list, delete_list,
113
 
                                                  insert_list)
114
 
                    delete_list, insert_list = [], []
115
 
                line_list.append(util.Container(old_lineno=line.old_lineno,
116
 
                                                new_lineno=line.new_lineno,
117
 
                                                old_line=wrapped_line,
118
 
                                                new_line=wrapped_line,
119
 
                                                old_type=line.type,
120
 
                                                new_type=line.type))
121
 
            elif line.type == 'delete':
122
 
                delete_list.append((line.old_lineno, wrapped_line, line.type))
123
 
            elif line.type == 'insert':
124
 
                insert_list.append((line.new_lineno, wrapped_line, line.type))
125
 
        if len(delete_list) or len(insert_list):
126
 
            _process_side_by_side_buffers(line_list, delete_list, insert_list)
127
 
        out_chunk_list.append(util.Container(diff=line_list))
128
 
    return out_chunk_list
129
 
 
130
 
 
131
70
def is_branch(folder):
132
71
    try:
133
72
        bzrlib.branch.Branch.open(folder)
654
593
        for entry, changes in zip(entries, changes_list):
655
594
            entry.changes = changes
656
595
 
657
 
    def get_change_with_diff(self, revid, compare_revid=None):
658
 
        change = self.get_changes([revid])[0]
659
 
 
660
 
        if compare_revid is None:
661
 
            if change.parents:
662
 
                compare_revid = change.parents[0].revid
663
 
            else:
664
 
                compare_revid = 'null:'
665
 
 
666
 
        rev_tree1 = self._branch.repository.revision_tree(compare_revid)
667
 
        rev_tree2 = self._branch.repository.revision_tree(revid)
668
 
        delta = rev_tree2.changes_from(rev_tree1)
669
 
 
670
 
        change.changes = self.parse_delta(delta)
671
 
        change.changes.modified = self._parse_diffs(rev_tree1,
672
 
                                                    rev_tree2,
673
 
                                                    delta)
674
 
 
675
 
        return change
676
 
 
677
596
    def get_file(self, file_id, revid):
678
597
        "returns (path, filename, data)"
679
598
        inv = self.get_inventory(revid)
684
603
            path = '/' + path
685
604
        return path, inv_entry.name, rev_tree.get_file_text(file_id)
686
605
 
687
 
    def _parse_diffs(self, old_tree, new_tree, delta):
688
 
        """
689
 
        Return a list of processed diffs, in the format::
690
 
 
691
 
            list(
692
 
                filename: str,
693
 
                file_id: str,
694
 
                chunks: list(
695
 
                    diff: list(
696
 
                        old_lineno: int,
697
 
                        new_lineno: int,
698
 
                        type: str('context', 'delete', or 'insert'),
699
 
                        line: str,
700
 
                    ),
701
 
                ),
702
 
            )
703
 
        """
704
 
        process = []
705
 
        out = []
706
 
 
707
 
        for old_path, new_path, fid, \
708
 
            kind, text_modified, meta_modified in delta.renamed:
709
 
            if text_modified:
710
 
                process.append((old_path, new_path, fid, kind))
711
 
        for path, fid, kind, text_modified, meta_modified in delta.modified:
712
 
            process.append((path, path, fid, kind))
713
 
 
714
 
        for old_path, new_path, fid, kind in process:
715
 
            old_lines = old_tree.get_file_lines(fid)
716
 
            new_lines = new_tree.get_file_lines(fid)
717
 
            buffer = StringIO()
718
 
            if old_lines != new_lines:
719
 
                try:
720
 
                    bzrlib.diff.internal_diff(old_path, old_lines,
721
 
                                              new_path, new_lines, buffer)
722
 
                except bzrlib.errors.BinaryFile:
723
 
                    diff = ''
724
 
                else:
725
 
                    diff = buffer.getvalue()
726
 
            else:
727
 
                diff = ''
728
 
            out.append(util.Container(
729
 
                          filename=rich_filename(new_path, kind),
730
 
                          file_id=fid,
731
 
                          chunks=self._process_diff(diff),
732
 
                          raw_diff=diff))
733
 
 
734
 
        return out
735
 
 
736
 
    def _process_diff(self, diff):
737
 
        # doesn't really need to be a method; could be static.
738
 
        chunks = []
739
 
        chunk = None
740
 
        for line in diff.splitlines():
741
 
            if len(line) == 0:
742
 
                continue
743
 
            if line.startswith('+++ ') or line.startswith('--- '):
744
 
                continue
745
 
            if line.startswith('@@ '):
746
 
                # new chunk
747
 
                if chunk is not None:
748
 
                    chunks.append(chunk)
749
 
                chunk = util.Container()
750
 
                chunk.diff = []
751
 
                split_lines = line.split(' ')[1:3]
752
 
                lines = [int(x.split(',')[0][1:]) for x in split_lines]
753
 
                old_lineno = lines[0]
754
 
                new_lineno = lines[1]
755
 
            elif line.startswith(' '):
756
 
                chunk.diff.append(util.Container(old_lineno=old_lineno,
757
 
                                                 new_lineno=new_lineno,
758
 
                                                 type='context',
759
 
                                                 line=line[1:]))
760
 
                old_lineno += 1
761
 
                new_lineno += 1
762
 
            elif line.startswith('+'):
763
 
                chunk.diff.append(util.Container(old_lineno=None,
764
 
                                                 new_lineno=new_lineno,
765
 
                                                 type='insert', line=line[1:]))
766
 
                new_lineno += 1
767
 
            elif line.startswith('-'):
768
 
                chunk.diff.append(util.Container(old_lineno=old_lineno,
769
 
                                                 new_lineno=None,
770
 
                                                 type='delete', line=line[1:]))
771
 
                old_lineno += 1
772
 
            else:
773
 
                chunk.diff.append(util.Container(old_lineno=None,
774
 
                                                 new_lineno=None,
775
 
                                                 type='unknown',
776
 
                                                 line=repr(line)))
777
 
        if chunk is not None:
778
 
            chunks.append(chunk)
779
 
        return chunks
780
 
 
781
606
    def parse_delta(self, delta):
782
607
        """
783
608
        Return a nested data structure containing the changes in a delta::
816
641
        return util.Container(added=added, renamed=renamed,
817
642
                              removed=removed, modified=modified)
818
643
 
819
 
    @staticmethod
820
 
    def add_side_by_side(changes):
821
 
        # FIXME: this is a rotten API.
822
 
        for change in changes:
823
 
            for m in change.changes.modified:
824
 
                m.sbs_chunks = _make_side_by_side(m.chunks)
825
 
 
826
644
    def annotate_file(self, file_id, revid):
827
645
        z = time.time()
828
646
        lineno = 1