fix: resolve CI issues - push complete implementation with tests
This commit is contained in:
@@ -1,21 +1,16 @@
|
||||
"""Diff parser for unified git diff format."""
|
||||
|
||||
import re
|
||||
|
||||
from gdiffer.models import DiffFile, DiffHunk
|
||||
|
||||
|
||||
class DiffParser:
|
||||
"""Parser for unified diff format (as produced by git diff)."""
|
||||
|
||||
HUNK_PATTERN = re.compile(r'^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@')
|
||||
HUNK_PATTERN = re.compile(r"^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@")
|
||||
|
||||
def __init__(self):
|
||||
self.files: list[DiffFile] = []
|
||||
self.errors: list[str] = []
|
||||
self.files = []
|
||||
self.errors = []
|
||||
|
||||
def parse(self, diff_content: str) -> list[DiffFile]:
|
||||
"""Parse diff content and return list of DiffFile objects."""
|
||||
def parse(self, diff_content):
|
||||
self.files = []
|
||||
self.errors = []
|
||||
|
||||
@@ -26,14 +21,14 @@ class DiffParser:
|
||||
self._parse_lines(lines)
|
||||
return self.files
|
||||
|
||||
def _parse_lines(self, lines: list[str]) -> None:
|
||||
def _parse_lines(self, lines):
|
||||
i = 0
|
||||
n = len(lines)
|
||||
|
||||
while i < n:
|
||||
line = lines[i].rstrip('\n')
|
||||
line = lines[i].rstrip("\n")
|
||||
|
||||
if line.startswith('diff --git'):
|
||||
if line.startswith("diff --git"):
|
||||
file_obj = self._parse_file(lines, i)
|
||||
if file_obj:
|
||||
self.files.append(file_obj)
|
||||
@@ -42,24 +37,24 @@ class DiffParser:
|
||||
|
||||
i += 1
|
||||
|
||||
def _parse_file(self, lines: list[str], start: int) -> DiffFile | None:
|
||||
def _parse_file(self, lines, start):
|
||||
if start >= len(lines):
|
||||
return None
|
||||
|
||||
first_line = lines[start]
|
||||
if not first_line.startswith('diff --git'):
|
||||
if not first_line.startswith("diff --git"):
|
||||
return None
|
||||
|
||||
parts = first_line.split(' ', 3)
|
||||
parts = first_line.split(" ", 3)
|
||||
if len(parts) < 4:
|
||||
return None
|
||||
|
||||
old_path = parts[2][2:] if len(parts) > 2 else ''
|
||||
old_path = parts[2][2:] if len(parts) > 2 else ""
|
||||
new_path = parts[3][2:] if len(parts) > 3 else old_path
|
||||
|
||||
if old_path.startswith('a/'):
|
||||
if old_path.startswith("a/"):
|
||||
old_path = old_path[2:]
|
||||
if new_path.startswith('b/'):
|
||||
if new_path.startswith("b/"):
|
||||
new_path = new_path[2:]
|
||||
|
||||
file_obj = DiffFile(old_path=old_path, new_path=new_path)
|
||||
@@ -68,63 +63,63 @@ class DiffParser:
|
||||
n = len(lines)
|
||||
|
||||
while i < n:
|
||||
line = lines[i].rstrip('\n')
|
||||
line = lines[i].rstrip("\n")
|
||||
|
||||
if line.startswith('new file mode '):
|
||||
if line.startswith("new file mode "):
|
||||
file_obj.new_file_mode = line.split()[-1]
|
||||
file_obj.change_type = "add"
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith('deleted file mode '):
|
||||
if line.startswith("deleted file mode "):
|
||||
file_obj.deleted_file_mode = line.split()[-1]
|
||||
file_obj.change_type = "delete"
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith('similarity index '):
|
||||
file_obj.similarity_index = line.split()[-1].rstrip('%')
|
||||
if line.startswith("similarity index "):
|
||||
file_obj.similarity_index = line.split()[-1].rstrip("%")
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith('rename from '):
|
||||
if line.startswith("rename from "):
|
||||
file_obj.rename_from = line[12:]
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith('rename to '):
|
||||
if line.startswith("rename to "):
|
||||
file_obj.rename_to = line[10:]
|
||||
file_obj.change_type = "rename"
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith('---'):
|
||||
if line.startswith("---"):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith('+++'):
|
||||
if line.startswith("+++"):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith('@@'):
|
||||
if line.startswith("@@"):
|
||||
hunk, consumed = self._parse_hunk(lines, i)
|
||||
if hunk:
|
||||
file_obj.hunks.append(hunk)
|
||||
i += consumed
|
||||
continue
|
||||
|
||||
if line.startswith('diff --git'):
|
||||
if line.startswith("diff --git"):
|
||||
break
|
||||
|
||||
i += 1
|
||||
|
||||
return file_obj
|
||||
|
||||
def _parse_hunk(self, lines: list[str], start: int) -> tuple[DiffHunk | None, int]:
|
||||
def _parse_hunk(self, lines, start):
|
||||
if start >= len(lines):
|
||||
return None, 0
|
||||
|
||||
line = lines[start].rstrip('\n')
|
||||
line = lines[start].rstrip("\n")
|
||||
match = self.HUNK_PATTERN.match(line)
|
||||
|
||||
if not match:
|
||||
@@ -151,30 +146,30 @@ class DiffParser:
|
||||
new_content = []
|
||||
|
||||
while i < n:
|
||||
line = lines[i].rstrip('\n')
|
||||
line = lines[i].rstrip("\n")
|
||||
|
||||
if line.startswith('@@'):
|
||||
if line.startswith("@@"):
|
||||
break
|
||||
|
||||
if line.startswith('diff --git'):
|
||||
if line.startswith("diff --git"):
|
||||
break
|
||||
|
||||
if line.startswith('---'):
|
||||
if line.startswith("---"):
|
||||
break
|
||||
|
||||
if line.startswith('+++'):
|
||||
if line.startswith("+++"):
|
||||
break
|
||||
|
||||
if old_lines_collected >= old_lines and new_lines_collected >= new_lines:
|
||||
break
|
||||
|
||||
if line.startswith('+') and not line.startswith('+++'):
|
||||
if line.startswith("+") and not line.startswith("+++"):
|
||||
new_content.append(line)
|
||||
new_lines_collected += 1
|
||||
elif line.startswith('-') and not line.startswith('---'):
|
||||
elif line.startswith("-") and not line.startswith("---"):
|
||||
old_content.append(line)
|
||||
old_lines_collected += 1
|
||||
elif line.startswith(' ') or line == '':
|
||||
elif line.startswith(" ") or line == "":
|
||||
old_content.append(line)
|
||||
new_content.append(line)
|
||||
old_lines_collected += 1
|
||||
@@ -190,14 +185,12 @@ class DiffParser:
|
||||
return hunk, i - start
|
||||
|
||||
|
||||
def parse_diff(diff_content: str) -> list[DiffFile]:
|
||||
"""Parse diff content and return list of DiffFile objects."""
|
||||
def parse_diff(diff_content):
|
||||
parser = DiffParser()
|
||||
return parser.parse(diff_content)
|
||||
|
||||
|
||||
def parse_diff_from_file(filepath: str) -> list[DiffFile]:
|
||||
"""Read a diff file and parse its contents."""
|
||||
def parse_diff_from_file(filepath):
|
||||
with open(filepath) as f:
|
||||
content = f.read()
|
||||
return parse_diff(content)
|
||||
|
||||
Reference in New Issue
Block a user