2 ## Copyright (c) 2012 The WebM project authors. All Rights Reserved.
4 ## Use of this source code is governed by a BSD-style license
5 ## that can be found in the LICENSE file in the root of the source
6 ## tree. An additional intellectual property rights grant can be found
7 ## in the file PATENTS. All contributing project authors may
8 ## be found in the AUTHORS file in the root of the source tree.
10 """Classes for representing diff pieces."""
12 __author__
= "jkoleszar@google.com"
17 class DiffLines(object):
18 """A container for one half of a diff."""
20 def __init__(self
, filename
, offset
, length
):
21 self
.filename
= filename
25 self
.delta_line_nums
= []
27 def Append(self
, line
):
30 self
.delta_line_nums
.append(self
.offset
+ l
)
31 self
.lines
.append(line
[1:])
32 assert l
+1 <= self
.length
35 return len(self
.lines
) == self
.length
37 def __contains__(self
, item
):
38 return item
>= self
.offset
and item
<= self
.offset
+ self
.length
- 1
41 class DiffHunk(object):
42 """A container for one diff hunk, consisting of two DiffLines."""
44 def __init__(self
, header
, file_a
, file_b
, start_a
, len_a
, start_b
, len_b
):
46 self
.left
= DiffLines(file_a
, start_a
, len_a
)
47 self
.right
= DiffLines(file_b
, start_b
, len_b
)
50 def Append(self
, line
):
51 """Adds a line to the DiffHunk and its DiffLines children."""
53 self
.left
.Append(line
)
55 self
.right
.Append(line
)
57 self
.left
.Append(line
)
58 self
.right
.Append(line
)
60 # Ignore newline messages from git diff.
63 assert False, ("Unrecognized character at start of diff line "
65 self
.lines
.append(line
)
68 return self
.left
.Complete() and self
.right
.Complete()
71 return "DiffHunk(%s, %s, len %d)" % (
72 self
.left
.filename
, self
.right
.filename
,
73 max(self
.left
.length
, self
.right
.length
))
76 def ParseDiffHunks(stream
):
77 """Walk a file-like object, yielding DiffHunks as they're parsed."""
79 file_regex
= re
.compile(r
"(\+\+\+|---) (\S+)")
80 range_regex
= re
.compile(r
"@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))?")
83 line
= stream
.readline()
89 diff_file
= file_regex
.match(line
)
91 if line
.startswith("---"):
93 a
= diff_file
.group(2)
95 if line
.startswith("+++"):
97 b
= diff_file
.group(2)
100 # Parse offset/lengths
101 diffrange
= range_regex
.match(line
)
103 if diffrange
.group(2):
104 start_a
= int(diffrange
.group(1))
105 len_a
= int(diffrange
.group(3))
108 len_a
= int(diffrange
.group(1))
110 if diffrange
.group(5):
111 start_b
= int(diffrange
.group(4))
112 len_b
= int(diffrange
.group(6))
115 len_b
= int(diffrange
.group(4))
117 header
= [a_line
, b_line
, line
]
118 hunk
= DiffHunk(header
, a
, b
, start_a
, len_a
, start_b
, len_b
)
120 # Add the current line to the hunk
123 # See if the whole hunk has been parsed. If so, yield it and prepare
129 # Partial hunks are a parse error