pub fn parse_unified_diff(diff_text: &str) -> Vec<Hunk>Expand description
Parse the output of git diff --unified=N into hunks.
Tolerant by design: anything it does not recognise is skipped rather than
erroring, because a diff that cannot be parsed must not take the gate down.
The rules, which follow git’s own reader (apply.c):
- A hunk body is exactly as long as its
@@counts say. Context consumes a line from each side, a removal one old line, an addition one new line, and\ No newline at end of filenone; that marker refers to the preceding line and never becomes aHunkLine. Every body line is prefixed, so no content can end a body early: an added source line that reads++ /dev/nullarrives as+++ /dev/nulland is still an addition, not a deletion header that hides the rest of the file from review, and a removed one reading-- xarrives as--- xand is still a removal. - An empty body line is an empty context line, as
diff.suppressBlankEmptyprints it. Any other unprefixed line, or one the counts leave no room for, ends the hunk early and is then read as a header. - The file path comes from the
+++label, never fromdiff --git. That line carries two paths with no unambiguous separator, so any “findb/” rule captures the wrong span for a repository path that itself containsb/(src/b/mod.rs). The label is decoded as git quoted it, and the tab git appends to a name containing a space is dropped - seenew_file_path.+++ /dev/nullmarks a deletion, which has nothing to analyze, so its hunks are dropped. - A malformed
@@produces no hunk, and nothing after it is attributed to the hunk before it.