Skip to main content

parse_unified_diff

Function parse_unified_diff 

Source
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 file none; that marker refers to the preceding line and never becomes a HunkLine. Every body line is prefixed, so no content can end a body early: an added source line that reads ++ /dev/null arrives as +++ /dev/null and is still an addition, not a deletion header that hides the rest of the file from review, and a removed one reading -- x arrives as --- x and is still a removal.
  • An empty body line is an empty context line, as diff.suppressBlankEmpty prints 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 from diff --git. That line carries two paths with no unambiguous separator, so any “find b/” rule captures the wrong span for a repository path that itself contains b/ (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 - see new_file_path. +++ /dev/null marks 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.