/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/controllers/filediff_ui.py

  • Committer: Ubuntu One Auto Copilot
  • Author(s): Jelmer Vernooij
  • Date: 2022-08-30 10:28:23 UTC
  • mfrom: (533.1.1 trunk)
  • Revision ID: otto-copilot@canonical.com-20220830102823-u3w6efosxw5s086s
Cope with moved errors NoSuchFile and FileExists in newer versions of Breezy.

Merged from https://code.launchpad.net/~jelmer/loggerhead/moved-errors/+merge/429073

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from io import BytesIO
 
2
 
 
3
from breezy import (
 
4
    diff,
 
5
    errors,
 
6
    urlutils,
 
7
    )
 
8
try:
 
9
    from breezy.transport import NoSuchFile
 
10
except ImportError:
 
11
    from breezy.errors import NoSuchFile
 
12
from breezy.tree import find_previous_path
 
13
 
 
14
from .. import util
 
15
from ..controllers import TemplatedBranchView
 
16
 
 
17
 
 
18
def _process_diff(difftext):
 
19
    chunks = []
 
20
    chunk = None
 
21
 
 
22
    def decode_line(line):
 
23
        return line.decode('utf-8', 'replace')
 
24
    for line in difftext.splitlines():
 
25
        if len(line) == 0:
 
26
            continue
 
27
        if line.startswith(b'+++ ') or line.startswith(b'--- '):
 
28
            continue
 
29
        if line.startswith(b'@@ '):
 
30
            # new chunk
 
31
            if chunk is not None:
 
32
                chunks.append(chunk)
 
33
            chunk = util.Container()
 
34
            chunk.diff = []
 
35
            split_lines = line.split(b' ')[1:3]
 
36
            lines = [int(x.split(b',')[0][1:]) for x in split_lines]
 
37
            old_lineno = lines[0]
 
38
            new_lineno = lines[1]
 
39
        elif line.startswith(b' '):
 
40
            chunk.diff.append(util.Container(old_lineno=old_lineno,
 
41
                                             new_lineno=new_lineno,
 
42
                                             type='context',
 
43
                                             line=decode_line(line[1:])))
 
44
            old_lineno += 1
 
45
            new_lineno += 1
 
46
        elif line.startswith(b'+'):
 
47
            chunk.diff.append(util.Container(
 
48
                old_lineno=None,
 
49
                new_lineno=new_lineno,
 
50
                type='insert', line=decode_line(line[1:])))
 
51
            new_lineno += 1
 
52
        elif line.startswith(b'-'):
 
53
            chunk.diff.append(util.Container(
 
54
                old_lineno=old_lineno,
 
55
                new_lineno=None,
 
56
                type='delete', line=decode_line(line[1:])))
 
57
            old_lineno += 1
 
58
        else:
 
59
            chunk.diff.append(util.Container(
 
60
                old_lineno=None,
 
61
                new_lineno=None,
 
62
                type='unknown',
 
63
                line=repr(line)))
 
64
    if chunk is not None:
 
65
        chunks.append(chunk)
 
66
    return chunks
 
67
 
 
68
 
 
69
def diff_chunks_for_file(repository, filename, compare_revid, revid,
 
70
                         context_lines=None):
 
71
    if context_lines is None:
 
72
        context_lines = 3
 
73
    lines = {}
 
74
    compare_tree = repository.revision_tree(compare_revid)
 
75
    tree = repository.revision_tree(revid)
 
76
    try:
 
77
        lines[revid] = tree.get_file_lines(filename)
 
78
    except NoSuchFile:
 
79
        lines[revid] = []
 
80
        lines[compare_revid] = compare_tree.get_file_lines(filename)
 
81
    else:
 
82
        compare_filename = find_previous_path(tree, compare_tree, filename)
 
83
        if compare_filename is not None:
 
84
            lines[compare_revid] = compare_tree.get_file_lines(compare_filename)
 
85
        else:
 
86
            lines[compare_revid] = []
 
87
 
 
88
    buffer = BytesIO()
 
89
    try:
 
90
        diff.internal_diff(
 
91
            '', lines[compare_revid], '', lines[revid], buffer,
 
92
            context_lines=context_lines)
 
93
    except errors.BinaryFile:
 
94
        difftext = b''
 
95
    else:
 
96
        difftext = buffer.getvalue()
 
97
 
 
98
    return _process_diff(difftext)
 
99
 
 
100
 
 
101
class FileDiffUI(TemplatedBranchView):
 
102
 
 
103
    template_name = 'filediff'
 
104
    supports_json = True
 
105
 
 
106
    def get_values(self, path, kwargs, headers):
 
107
        revid = urlutils.unquote_to_bytes(self.args[0])
 
108
        compare_revid = urlutils.unquote_to_bytes(self.args[1])
 
109
        filename = urlutils.unquote(self.args[2])
 
110
 
 
111
        try:
 
112
            context_lines = int(kwargs['context'])
 
113
        except (KeyError, ValueError):
 
114
            context_lines = None
 
115
 
 
116
        chunks = diff_chunks_for_file(
 
117
            self._history._branch.repository, filename, compare_revid, revid,
 
118
            context_lines=context_lines)
 
119
 
 
120
        return {
 
121
            'chunks': chunks,
 
122
        }