Expand description
vcs-diff — the shared git-format unified-diff model and parser for the
vcs-toolkit-rs workspace.
git diff and jj diff --git emit byte-identical git-format unified
diffs, so vcs-git and vcs-jj share one model and one parser here rather
than each carrying a copy that could silently drift. This is the foundational
crate both depend on: std only, no async, no subprocess — pure data types
and pure functions over text the wrapper crates obtained elsewhere.
§The surface
parse_diff— the entry point. Turns git-format diff text into oneFileDiffper file; the same call servesgit diffandjj diff --gitoutput alike. Pure and total: arbitrary CLI bytes in, never a panic.FileDiff— one file’s entry: itsChangeKind, the forward-slash-normalisedpath(andold_pathfor a rename), theHunks, and the verbatimrawsection for callers that display text.Hunk— a single@@ … @@block: the old/new line ranges, the section heading, and a body of **DiffLine**s (Context/Added/Removed), each with its leading marker and line terminator stripped.ChangeKind— how the file changed:Added/Modified/Deleted/Renamed.DiffStat— the aggregatefiles_changed/insertions/deletionsshape bothgit diff --shortstatandjj diff --statparse into.Version+parse_dotted_version— a numericmajor.minor.patch(itOrds, so a caller can gate on a minimum) read tolerantly from a<tool> --versionbanner.
The wrapper crates re-export these (e.g. vcs_git::FileDiff,
vcs_git::parse_diff, vcs_git::GitVersion), so consumers rarely name this
crate directly.
§Recipes
Parse a one-file modify diff and read the structured result — pure, so this runs as written:
use vcs_diff::{parse_diff, ChangeKind, DiffLine};
let text = "\
diff --git a/f b/f
--- a/f
+++ b/f
@@ -1,2 +1,2 @@ fn main()
ctx
-old
+new
";
let files = parse_diff(text);
assert_eq!(files.len(), 1);
assert_eq!(files[0].change, ChangeKind::Modified);
assert_eq!(files[0].path, "f");
let hunk = &files[0].hunks[0];
assert_eq!((hunk.old_start, hunk.new_start), (1, 1));
assert_eq!(hunk.section, "fn main()");
assert_eq!(hunk.lines, vec![
DiffLine::Context("ctx".into()),
DiffLine::Removed("old".into()),
DiffLine::Added("new".into()),
]);§Features
Structs§
- Diff
Stat - Aggregate line/file counts from a diff stat (
git diff --shortstat,jj diff --stat). - File
Diff - One file’s entry in a parsed git-format unified diff (
git difforjj diff --git). - Hunk
- A single
@@ … @@hunk within aFileDiff. - Version
- A parsed CLI version (
major.minor.patch).Ordcompares numerically, so a caller can gate a feature on a minimum version;Hashlets it key a map (e.g. a per-version capability cache).
Enums§
- Change
Kind - How a file changed in a unified diff.
- Diff
Line - One line inside a
Hunk, tagged by its role. The stored text excludes the leading/+/-marker and the line terminator — a CRLF-origin diff’s trailing\ris stripped along with the\n, so reconstruct exact bytes fromFileDiff::raw, not from these lines.
Functions§
- parse_
diff - Parse a git-format unified diff into one
FileDiffper file. Works ongit diffandjj diff --gitoutput alike. Public so a consumer can parse diff text it obtained by other means. - parse_
dotted_ version - Find the first
N.N[.N…]token inrawand return its leading three numeric components (a missing patch reads as 0). Each component is the token’s leading digits, so0-devor1.windowstrailers don’t break parsing — this handlesgit version 2.54.0.windows.1,jj 0.42.0,2.41.0-rc1, etc.