-
Notifications
You must be signed in to change notification settings - Fork 0
review diff_parser
Runs git diff and parses raw unified diff text into structured DiffFile objects using the unidiff library.
| Term | Definition | Example |
|---|---|---|
| diff | The set of changes between two versions of code, showing added (+) and removed (-) lines. |
- old_line\n+ new_line shows old_line was replaced with new_line. |
| hunk | A contiguous block of changes within a diff. One diff can contain multiple hunks (changes in different parts of a file). | A diff might have hunk 1 (lines 10-15 changed) and hunk 2 (lines 80-85 changed). |
Runs git diff as a subprocess and returns the raw unified diff text as a string.
By default, returns ALL changes: staged, unstaged, AND new untracked files.
| Param | Type | Default | Purpose |
|---|---|---|---|
staged |
bool |
False |
If True, diffs ONLY staged changes (narrow mode — no unstaged or untracked) |
target_branch |
str | None |
None |
Diff working tree against this branch (two-dot: committed + staged + unstaged + untracked) |
commit |
str | None |
None |
If set, shows diff for that specific commit (SHA or ref). No untracked files. |
since_commit |
str | None |
None |
Diff from this commit to working tree + untracked. |
repo_path |
str | None |
None |
Working directory for the git command |
Priority: commit > since_commit > target_branch > staged > default (git diff HEAD).
commit → git diff <sha>~1 <sha> (historical, no untracked)
since_commit → git diff <sha> + untracked
target_branch → git diff <branch> + untracked (two-dot diff)
staged=True → git diff --staged (narrow, no untracked)
default → git diff HEAD + untracked
default (no HEAD)→ git diff --cached + untracked (empty repo)
Input: repo_path="/home/user/myapp" (no other args)
Runs git diff HEAD --unified=5 → captures staged + unstaged changes.
Then appends synthetic diffs for untracked files via _synthetic_untracked_diff().
Returns combined diff text.
Input: target_branch="main", repo_path=None
Runs git diff main --unified=5 → two-dot diff showing everything different from main's tip (committed + staged + unstaged).
Then appends synthetic diffs for untracked files.
Input: commit="abc1234", staged=True, target_branch="main", repo_path="/project"
commit takes highest priority — staged and target_branch are ignored.
Runs git diff abc1234~1 abc1234 → shows what that commit changed.
No untracked files appended (historical snapshot).
Generates unified-diff text for untracked files not yet staged.
Runs git ls-files --others --exclude-standard and builds a synthetic diff for each file.
Skips: binary files (null byte in first 8KB), files > 512KB, symlinks, non-UTF-8 files.
Parses a raw unified diff string into a list of DiffFile objects using the unidiff.PatchSet parser.
| Param | Type | Purpose |
|---|---|---|
diff_text |
str |
Raw unified diff text from git diff
|
Input:
diff_text = """diff --git a/math.py b/math.py
--- a/math.py
+++ b/math.py
@@ -10,3 +10,3 @@
def add(a, b):
- return a - b
+ return a + b
"""
Walkthrough:
Line 28–29: diff_text.strip() is non-empty → proceed
Line 31: patch = PatchSet(diff_text) → parses into a PatchSet with 1 PatchedFile
Line 32: diff_files = []
Loop — patched_file = first (and only) PatchedFile for math.py:
Line 35: hunks = []
Loop — hunk = first hunk (the @@ block):
Line 37: lines = []
Loop — line = first line (def add(a, b):):
Line 38–40: line.is_added → False, line.is_removed → False
Line 44–45: → change_type = "context", line_no = 10 (target_line_no)
Line 47–50: appends ChangedLine(line_number=10, content="def add(a, b):\n", change_type="context")
Loop — line = second line (- return a - b):
Line 41–43: line.is_removed → True → change_type = "removed", line_no = 11 (source_line_no)
Line 47–50: appends ChangedLine(line_number=11, content=" return a - b\n", change_type="removed")
Loop — line = third line (+ return a + b):
Line 38–40: line.is_added → True → change_type = "added", line_no = 11 (target_line_no)
Line 47–50: appends ChangedLine(line_number=11, content=" return a + b\n", change_type="added")
Line 52–55: appends DiffHunk(start_line=10, end_line=13, lines=[...3 ChangedLines...])
Line 57–65: appends DiffFile(...):
DiffFile(
file_path="math.py",
language=detect_language(Path("math.py")), → "python"
hunks=[DiffHunk(start_line=10, end_line=13, lines=[...])],
is_new_file=False,
is_deleted=False,
added_lines=1,
removed_lines=1,
)
Return: [DiffFile(file_path="math.py", language="python", added_lines=1, removed_lines=1, ...)]