xref: /aosp_15_r20/external/libvpx/tools/diff.py (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*fb1b10abSAndroid Build Coastguard Worker##  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker##
4*fb1b10abSAndroid Build Coastguard Worker##  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker##  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker##  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker##  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker##  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker##
10*fb1b10abSAndroid Build Coastguard Worker"""Classes for representing diff pieces."""
11*fb1b10abSAndroid Build Coastguard Worker
12*fb1b10abSAndroid Build Coastguard Worker__author__ = "[email protected]"
13*fb1b10abSAndroid Build Coastguard Worker
14*fb1b10abSAndroid Build Coastguard Workerimport re
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker
17*fb1b10abSAndroid Build Coastguard Workerclass DiffLines(object):
18*fb1b10abSAndroid Build Coastguard Worker    """A container for one half of a diff."""
19*fb1b10abSAndroid Build Coastguard Worker
20*fb1b10abSAndroid Build Coastguard Worker    def __init__(self, filename, offset, length):
21*fb1b10abSAndroid Build Coastguard Worker        self.filename = filename
22*fb1b10abSAndroid Build Coastguard Worker        self.offset = offset
23*fb1b10abSAndroid Build Coastguard Worker        self.length = length
24*fb1b10abSAndroid Build Coastguard Worker        self.lines = []
25*fb1b10abSAndroid Build Coastguard Worker        self.delta_line_nums = []
26*fb1b10abSAndroid Build Coastguard Worker
27*fb1b10abSAndroid Build Coastguard Worker    def Append(self, line):
28*fb1b10abSAndroid Build Coastguard Worker        l = len(self.lines)
29*fb1b10abSAndroid Build Coastguard Worker        if line[0] != " ":
30*fb1b10abSAndroid Build Coastguard Worker            self.delta_line_nums.append(self.offset + l)
31*fb1b10abSAndroid Build Coastguard Worker        self.lines.append(line[1:])
32*fb1b10abSAndroid Build Coastguard Worker        assert l+1 <= self.length
33*fb1b10abSAndroid Build Coastguard Worker
34*fb1b10abSAndroid Build Coastguard Worker    def Complete(self):
35*fb1b10abSAndroid Build Coastguard Worker        return len(self.lines) == self.length
36*fb1b10abSAndroid Build Coastguard Worker
37*fb1b10abSAndroid Build Coastguard Worker    def __contains__(self, item):
38*fb1b10abSAndroid Build Coastguard Worker        return item >= self.offset and item <= self.offset + self.length - 1
39*fb1b10abSAndroid Build Coastguard Worker
40*fb1b10abSAndroid Build Coastguard Worker
41*fb1b10abSAndroid Build Coastguard Workerclass DiffHunk(object):
42*fb1b10abSAndroid Build Coastguard Worker    """A container for one diff hunk, consisting of two DiffLines."""
43*fb1b10abSAndroid Build Coastguard Worker
44*fb1b10abSAndroid Build Coastguard Worker    def __init__(self, header, file_a, file_b, start_a, len_a, start_b, len_b):
45*fb1b10abSAndroid Build Coastguard Worker        self.header = header
46*fb1b10abSAndroid Build Coastguard Worker        self.left = DiffLines(file_a, start_a, len_a)
47*fb1b10abSAndroid Build Coastguard Worker        self.right = DiffLines(file_b, start_b, len_b)
48*fb1b10abSAndroid Build Coastguard Worker        self.lines = []
49*fb1b10abSAndroid Build Coastguard Worker
50*fb1b10abSAndroid Build Coastguard Worker    def Append(self, line):
51*fb1b10abSAndroid Build Coastguard Worker        """Adds a line to the DiffHunk and its DiffLines children."""
52*fb1b10abSAndroid Build Coastguard Worker        if line[0] == "-":
53*fb1b10abSAndroid Build Coastguard Worker            self.left.Append(line)
54*fb1b10abSAndroid Build Coastguard Worker        elif line[0] == "+":
55*fb1b10abSAndroid Build Coastguard Worker            self.right.Append(line)
56*fb1b10abSAndroid Build Coastguard Worker        elif line[0] == " ":
57*fb1b10abSAndroid Build Coastguard Worker            self.left.Append(line)
58*fb1b10abSAndroid Build Coastguard Worker            self.right.Append(line)
59*fb1b10abSAndroid Build Coastguard Worker        elif line[0] == "\\":
60*fb1b10abSAndroid Build Coastguard Worker            # Ignore newline messages from git diff.
61*fb1b10abSAndroid Build Coastguard Worker            pass
62*fb1b10abSAndroid Build Coastguard Worker        else:
63*fb1b10abSAndroid Build Coastguard Worker            assert False, ("Unrecognized character at start of diff line "
64*fb1b10abSAndroid Build Coastguard Worker                           "%r" % line[0])
65*fb1b10abSAndroid Build Coastguard Worker        self.lines.append(line)
66*fb1b10abSAndroid Build Coastguard Worker
67*fb1b10abSAndroid Build Coastguard Worker    def Complete(self):
68*fb1b10abSAndroid Build Coastguard Worker        return self.left.Complete() and self.right.Complete()
69*fb1b10abSAndroid Build Coastguard Worker
70*fb1b10abSAndroid Build Coastguard Worker    def __repr__(self):
71*fb1b10abSAndroid Build Coastguard Worker        return "DiffHunk(%s, %s, len %d)" % (
72*fb1b10abSAndroid Build Coastguard Worker            self.left.filename, self.right.filename,
73*fb1b10abSAndroid Build Coastguard Worker            max(self.left.length, self.right.length))
74*fb1b10abSAndroid Build Coastguard Worker
75*fb1b10abSAndroid Build Coastguard Worker
76*fb1b10abSAndroid Build Coastguard Workerdef ParseDiffHunks(stream):
77*fb1b10abSAndroid Build Coastguard Worker    """Walk a file-like object, yielding DiffHunks as they're parsed."""
78*fb1b10abSAndroid Build Coastguard Worker
79*fb1b10abSAndroid Build Coastguard Worker    file_regex = re.compile(r"(\+\+\+|---) (\S+)")
80*fb1b10abSAndroid Build Coastguard Worker    range_regex = re.compile(r"@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))?")
81*fb1b10abSAndroid Build Coastguard Worker    hunk = None
82*fb1b10abSAndroid Build Coastguard Worker    while True:
83*fb1b10abSAndroid Build Coastguard Worker        line = stream.readline()
84*fb1b10abSAndroid Build Coastguard Worker        if not line:
85*fb1b10abSAndroid Build Coastguard Worker            break
86*fb1b10abSAndroid Build Coastguard Worker
87*fb1b10abSAndroid Build Coastguard Worker        if hunk is None:
88*fb1b10abSAndroid Build Coastguard Worker            # Parse file names
89*fb1b10abSAndroid Build Coastguard Worker            diff_file = file_regex.match(line)
90*fb1b10abSAndroid Build Coastguard Worker            if diff_file:
91*fb1b10abSAndroid Build Coastguard Worker              if line.startswith("---"):
92*fb1b10abSAndroid Build Coastguard Worker                  a_line = line
93*fb1b10abSAndroid Build Coastguard Worker                  a = diff_file.group(2)
94*fb1b10abSAndroid Build Coastguard Worker                  continue
95*fb1b10abSAndroid Build Coastguard Worker              if line.startswith("+++"):
96*fb1b10abSAndroid Build Coastguard Worker                  b_line = line
97*fb1b10abSAndroid Build Coastguard Worker                  b = diff_file.group(2)
98*fb1b10abSAndroid Build Coastguard Worker                  continue
99*fb1b10abSAndroid Build Coastguard Worker
100*fb1b10abSAndroid Build Coastguard Worker            # Parse offset/lengths
101*fb1b10abSAndroid Build Coastguard Worker            diffrange = range_regex.match(line)
102*fb1b10abSAndroid Build Coastguard Worker            if diffrange:
103*fb1b10abSAndroid Build Coastguard Worker                if diffrange.group(2):
104*fb1b10abSAndroid Build Coastguard Worker                    start_a = int(diffrange.group(1))
105*fb1b10abSAndroid Build Coastguard Worker                    len_a = int(diffrange.group(3))
106*fb1b10abSAndroid Build Coastguard Worker                else:
107*fb1b10abSAndroid Build Coastguard Worker                    start_a = 1
108*fb1b10abSAndroid Build Coastguard Worker                    len_a = int(diffrange.group(1))
109*fb1b10abSAndroid Build Coastguard Worker
110*fb1b10abSAndroid Build Coastguard Worker                if diffrange.group(5):
111*fb1b10abSAndroid Build Coastguard Worker                    start_b = int(diffrange.group(4))
112*fb1b10abSAndroid Build Coastguard Worker                    len_b = int(diffrange.group(6))
113*fb1b10abSAndroid Build Coastguard Worker                else:
114*fb1b10abSAndroid Build Coastguard Worker                    start_b = 1
115*fb1b10abSAndroid Build Coastguard Worker                    len_b = int(diffrange.group(4))
116*fb1b10abSAndroid Build Coastguard Worker
117*fb1b10abSAndroid Build Coastguard Worker                header = [a_line, b_line, line]
118*fb1b10abSAndroid Build Coastguard Worker                hunk = DiffHunk(header, a, b, start_a, len_a, start_b, len_b)
119*fb1b10abSAndroid Build Coastguard Worker        else:
120*fb1b10abSAndroid Build Coastguard Worker            # Add the current line to the hunk
121*fb1b10abSAndroid Build Coastguard Worker            hunk.Append(line)
122*fb1b10abSAndroid Build Coastguard Worker
123*fb1b10abSAndroid Build Coastguard Worker            # See if the whole hunk has been parsed. If so, yield it and prepare
124*fb1b10abSAndroid Build Coastguard Worker            # for the next hunk.
125*fb1b10abSAndroid Build Coastguard Worker            if hunk.Complete():
126*fb1b10abSAndroid Build Coastguard Worker                yield hunk
127*fb1b10abSAndroid Build Coastguard Worker                hunk = None
128*fb1b10abSAndroid Build Coastguard Worker
129*fb1b10abSAndroid Build Coastguard Worker    # Partial hunks are a parse error
130*fb1b10abSAndroid Build Coastguard Worker    assert hunk is None
131