diff --git a/src/diff/tests.rs b/src/diff/tests.rs index e383a7d..01921d6 100644 --- a/src/diff/tests.rs +++ b/src/diff/tests.rs @@ -642,6 +642,81 @@ void Chunk_copy(Chunk *src, size_t src_start, Chunk *dst, size_t dst_start, size assert_patch!(original, a, expected_diffy); } +#[test] +fn suppress_blank_empty() { + let original = "\ +1 +2 +3 + +4 +"; + + let modified = "\ +1 +2 +3 + +5 +"; + + // Note that there is a space " " on the line after 3 + let expected = "\ +--- original ++++ modified +@@ -2,4 +2,4 @@ + 2 + 3 + +-4 ++5 +"; + + let f = PatchFormatter::new().suppress_blank_empty(false); + let patch = create_patch(original, modified); + let bpatch = create_patch_bytes(original.as_bytes(), modified.as_bytes()); + let patch_str = format!("{}", f.fmt_patch(&patch)); + let mut patch_bytes = Vec::new(); + f.write_patch_into(&bpatch, &mut patch_bytes).unwrap(); + + assert_eq!(patch_str, expected); + assert_eq!(patch_bytes, patch_str.as_bytes()); + assert_eq!(patch_bytes, expected.as_bytes()); + assert_eq!(apply(original, &patch).unwrap(), modified); + assert_eq!( + crate::apply_bytes(original.as_bytes(), &bpatch).unwrap(), + modified.as_bytes() + ); + + // Note that there is no space " " on the line after 3 + let expected_suppressed = "\ +--- original ++++ modified +@@ -2,4 +2,4 @@ + 2 + 3 + +-4 ++5 +"; + + let f = PatchFormatter::new().suppress_blank_empty(true); + let patch = create_patch(original, modified); + let bpatch = create_patch_bytes(original.as_bytes(), modified.as_bytes()); + let patch_str = format!("{}", f.fmt_patch(&patch)); + let mut patch_bytes = Vec::new(); + f.write_patch_into(&bpatch, &mut patch_bytes).unwrap(); + + assert_eq!(patch_str, expected_suppressed); + assert_eq!(patch_bytes, patch_str.as_bytes()); + assert_eq!(patch_bytes, expected_suppressed.as_bytes()); + assert_eq!(apply(original, &patch).unwrap(), modified); + assert_eq!( + crate::apply_bytes(original.as_bytes(), &bpatch).unwrap(), + modified.as_bytes() + ); +} + // In the event that a patch has an invalid hunk range we want to ensure that when apply is // attempting to search for a matching position to apply a hunk that the search algorithm runs in // time bounded by the length of the original image being patched. Before clamping the search space diff --git a/src/patch/format.rs b/src/patch/format.rs index 815e18b..0c815fc 100644 --- a/src/patch/format.rs +++ b/src/patch/format.rs @@ -10,6 +10,7 @@ use std::{ pub struct PatchFormatter { with_color: bool, with_missing_newline_message: bool, + suppress_blank_empty: bool, context: Style, delete: Style, @@ -26,6 +27,10 @@ impl PatchFormatter { with_color: false, with_missing_newline_message: true, + // TODO the default in git-diff and GNU diff is to have this set to false, on the next + // semver breaking release we should contemplate switching this to be false by default + suppress_blank_empty: true, + context: Style::new(), delete: Color::Red.normal(), insert: Color::Green.normal(), @@ -54,6 +59,20 @@ impl PatchFormatter { self } + /// Sets whether to suppress printing of a space before empty lines. + /// + /// Defaults to `true`. + /// + /// For more information you can refer to the [Omitting trailing blanks] manual page of GNU + /// diff or the [diff.suppressBlankEmpty] config for `git-diff`. + /// + /// [Omitting trailing blanks]: https://www.gnu.org/software/diffutils/manual/html_node/Trailing-Blanks.html + /// [diff.suppressBlankEmpty]: https://git-scm.com/docs/git-diff#Documentation/git-diff.txt-codediffsuppressBlankEmptycode + pub fn suppress_blank_empty(mut self, enable: bool) -> Self { + self.suppress_blank_empty = enable; + self + } + /// Returns a `Display` impl which can be used to print a Patch pub fn fmt_patch<'a>(&'a self, patch: &'a Patch<'a, str>) -> impl Display + 'a { PatchDisplay { f: self, patch } @@ -240,7 +259,7 @@ impl + ?Sized> LineDisplay<'_, T> { write!(w, "{}", style.prefix())?; } - if sign == ' ' && line == b"\n" { + if self.f.suppress_blank_empty && sign == ' ' && line == b"\n" { w.write_all(line)?; } else { write!(w, "{}", sign)?; @@ -274,7 +293,7 @@ impl Display for LineDisplay<'_, str> { write!(f, "{}", style.prefix())?; } - if sign == ' ' && *line == "\n" { + if self.f.suppress_blank_empty && sign == ' ' && *line == "\n" { write!(f, "{}", line)?; } else { write!(f, "{}{}", sign, line)?;