summaryrefslogtreecommitdiffstats
path: root/tools/githelper.py
diff options
context:
space:
mode:
authorJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2020-08-03 21:08:37 +0200
committerJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2020-08-03 21:08:37 +0200
commit1e7698d781179b4c0a05ee40d8245e7fd4896bd6 (patch)
tree72c4710a6411772a01758cbf9f6b1235a4e9fff3 /tools/githelper.py
parent5589ce8cac60eab8886efa5e234bfcd7a1565b9e (diff)
tools: Add various improvements for clang_format.py/githelper.py
Diffstat (limited to 'tools/githelper.py')
-rw-r--r--tools/githelper.py36
1 files changed, 27 insertions, 9 deletions
diff --git a/tools/githelper.py b/tools/githelper.py
index b7eb1656b1..29e9ee0a4e 100644
--- a/tools/githelper.py
+++ b/tools/githelper.py
@@ -26,41 +26,52 @@ def get_toplevel_path() -> str:
def get_changed_lines(
from_ref=None, filter_lines=None, include_files=None
) -> typing.Iterable[Line]:
- """Inspect `git diff` output, yields changed lines."""
+ """Inspect `git diff-index` output, yields changed lines."""
logger = logging.getLogger(__name__)
- cmd = ["git", "diff", "--unified=0", from_ref if from_ref else "HEAD"]
+ cmd = [
+ "git",
+ "diff-index",
+ "--patch",
+ "--unified=0",
+ from_ref if from_ref else "HEAD",
+ ]
if include_files:
cmd.extend(["--", *include_files])
logger.debug("Executing: %r", cmd)
proc = subprocess.run(cmd, capture_output=True)
proc.check_returncode()
current_file = None
- lines_left = 0
+ hunk_lines_left = 0
for line in proc.stdout.decode(errors="replace").splitlines():
match_file = re.match(r"^\+\+\+ b/(.*)$", line)
if match_file:
+ # Current line contains a diff filename
+ assert hunk_lines_left == 0
current_file = match_file.group(1)
- lines_left = 0
continue
match_lineno = re.match(
r"^@@ -(\d+(?:,\d+)?) \+([0-9]+(?:,[0-9]+)?) @@", line
)
if match_lineno:
+ # Current line contains a hunk header
+ assert current_file is not None
+ assert hunk_lines_left == 0
start_removed, _, length_removed = match_lineno.group(1).partition(
","
)
start_added, _, length_added = match_lineno.group(2).partition(",")
lineno_removed = int(start_removed)
lineno_added = int(start_added)
- lines_left = int(length_removed) if length_removed else 1
- lines_left += int(length_added) if length_added else 1
+ hunk_lines_left = int(length_removed) if length_removed else 1
+ hunk_lines_left += int(length_added) if length_added else 1
continue
- if lines_left and line:
- lines_left -= 1
+ if hunk_lines_left and line:
+ # Current line contains an added/removed line
+ hunk_lines_left -= 1
assert line[0] in ("+", "-")
if line.startswith("+"):
@@ -80,11 +91,18 @@ def get_changed_lines(
if filter_lines is None or filter_lines(lineobj):
yield lineobj
+ # If we reach this part, the line does not contain a diff filename or a
+ # hunk header and does not belog to a hunk. This means that this line
+ # will be ignored implicitly.
+
+ # Make sure we really parsed all lines from the last hunk
+ assert hunk_lines_left == 0
+
def get_changed_lines_grouped(
from_ref=None, filter_lines=None, include_files=None
) -> typing.Iterable[FileLines]:
- """Inspect `git diff` output, yields changed lines grouped by file."""
+ """Inspect `git diff-index` output, yields lines grouped by file."""
lines = get_changed_lines(from_ref, filter_lines, include_files)
for filename, file_lines in itertools.groupby(