From 1e03b7fe924ad24a6dfa0c199d8e78e029917ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= Date: Sun, 7 Jul 2024 12:30:05 +0100 Subject: [PATCH 1/2] Support Patch::write --- src/patch.rs | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/patch.rs b/src/patch.rs index c25b029..7fbab02 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -84,8 +84,14 @@ impl UnifiedPatch { } pub fn as_bytes(&self) -> Vec { - let mut lines = vec![ - format!( + let mut bytes = Vec::new(); + self.write(&mut bytes).unwrap(); + bytes + } + + pub fn write(&self, w: &mut W) -> std::io::Result<()> { + w.write_all( + &format!( "--- {}{}\n", String::from_utf8_lossy(&self.orig_name), match &self.orig_ts { @@ -94,7 +100,9 @@ impl UnifiedPatch { } ) .into_bytes(), - format!( + )?; + w.write_all( + &format!( "+++ {}{}\n", String::from_utf8_lossy(&self.mod_name), match &self.mod_ts { @@ -103,11 +111,11 @@ impl UnifiedPatch { } ) .into_bytes(), - ]; + )?; for hunk in &self.hunks { - lines.push(hunk.as_bytes()); + w.write_all(&hunk.as_bytes())?; } - lines.concat() + Ok(()) } pub fn parse_patch<'a, I>(iter_lines: I) -> Result @@ -214,7 +222,16 @@ pub enum HunkLine { } impl HunkLine { - fn get_str(&self, leadchar: u8) -> Vec { + pub fn char(&self) -> u8 { + match self { + Self::ContextLine(_) => b' ', + Self::InsertLine(_) => b'+', + Self::RemoveLine(_) => b'-', + } + } + + pub fn as_bytes(&self) -> Vec { + let leadchar = self.char(); match self { Self::ContextLine(contents) | Self::InsertLine(contents) @@ -229,18 +246,6 @@ impl HunkLine { } } - pub fn char(&self) -> u8 { - match self { - Self::ContextLine(_) => b' ', - Self::InsertLine(_) => b'+', - Self::RemoveLine(_) => b'-', - } - } - - pub fn as_bytes(&self) -> Vec { - self.get_str(self.char()) - } - pub fn parse_line(line: &[u8]) -> Result { if line.starts_with(b"\n") { Ok(Self::ContextLine(line.to_vec())) From 72377fcd675741e37588ec6c393788d894bf0928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= Date: Sun, 7 Jul 2024 12:35:37 +0100 Subject: [PATCH 2/2] Fix indentation for context lines --- src/patch.rs | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/patch.rs b/src/patch.rs index 7fbab02..5467fd2 100644 --- a/src/patch.rs +++ b/src/patch.rs @@ -113,7 +113,7 @@ impl UnifiedPatch { .into_bytes(), )?; for hunk in &self.hunks { - w.write_all(&hunk.as_bytes())?; + hunk.write(w)?; } Ok(()) } @@ -210,7 +210,7 @@ mod patch_tests { lines: vec![super::HunkLine::ContextLine(b"foo\n".to_vec())], }], }; - assert_eq!(patch.as_bytes(), b"--- foo\n+++ bar\n@@ -1 +2 @@\nfoo\n"); + assert_eq!(patch.as_bytes(), b"--- foo\n+++ bar\n@@ -1 +2 @@\n foo\n"); } } @@ -230,22 +230,25 @@ impl HunkLine { } } - pub fn as_bytes(&self) -> Vec { - let leadchar = self.char(); + pub fn contents(&self) -> &[u8] { match self { - Self::ContextLine(contents) - | Self::InsertLine(contents) - | Self::RemoveLine(contents) => { - let terminator = if !contents.ends_with(&b"\n"[..]) { - [b"\n".to_vec(), crate::parse::NO_NL.to_vec()].concat() - } else { - b"".to_vec() - }; - [vec![leadchar], contents.clone(), terminator].concat() - } + Self::ContextLine(bytes) => bytes, + Self::InsertLine(bytes) => bytes, + Self::RemoveLine(bytes) => bytes, } } + pub fn as_bytes(&self) -> Vec { + let leadchar = self.char(); + let contents = self.contents(); + let terminator = if !contents.ends_with(&b"\n"[..]) { + [b"\n".to_vec(), crate::parse::NO_NL.to_vec()].concat() + } else { + b"".to_vec() + }; + [vec![leadchar], contents.to_vec(), terminator].concat() + } + pub fn parse_line(line: &[u8]) -> Result { if line.starts_with(b"\n") { Ok(Self::ContextLine(line.to_vec())) @@ -415,16 +418,18 @@ impl Hunk { } } - pub fn as_bytes(&self) -> Vec { - let mut lines = vec![self.get_header()]; + pub fn write(&self, w: &mut W) -> std::io::Result<()> { + w.write_all(&self.get_header())?; for line in &self.lines { - lines.push(match line { - HunkLine::ContextLine(bytes) => bytes.clone(), - HunkLine::InsertLine(bytes) => bytes.clone(), - HunkLine::RemoveLine(bytes) => bytes.clone(), - }); + w.write_all(&line.as_bytes())?; } - lines.concat() + Ok(()) + } + + pub fn as_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + self.write(&mut bytes).unwrap(); + bytes } pub fn shift_to_mod(&self, pos: usize) -> Option {