Skip to content

Commit

Permalink
fix: Make parser handle meta lines in chunk
Browse files Browse the repository at this point in the history
The previous parser for Git chunks would fail to properly break
up chunks with any "meta lines" (my term for them) starting with
a `\` instead of `+` or `-`. This update to the parser means the
parser will now correctly handle those lines, but won't include
them in the patch string it constructs, as they're meta-commentary
on the diff itself and not part of the edits.

Signed-off-by: Andrew Lilley Brinker <[email protected]>
Co-authored-by: Julian Lanson <[email protected]>
  • Loading branch information
alilleybrinker and j-lanson committed Nov 4, 2024
1 parent 1195ea3 commit de67bed
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
20 changes: 20 additions & 0 deletions plugins/git/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ async fn commit_diffs(engine: &mut PluginEngine, repo: LocalGitRepo) -> Result<V
Error::UnspecifiedQueryState
})?;

if commits.len() != diffs.len() {
log::error!(
"parsed {} diffs but there are {} commits",
diffs.len(),
commits.len()
);
return Err(Error::UnspecifiedQueryState);
}

let commit_diffs = Iterator::zip(commits.iter(), diffs.iter())
.map(|(commit, diff)| CommitDiff {
commit: commit.clone(),
Expand Down Expand Up @@ -436,3 +445,14 @@ async fn main() -> Result<()> {
let args = Args::try_parse().unwrap();
PluginServer::register(GitPlugin {}).listen(args.port).await
}

#[cfg(test)]
mod test {
#[test]
fn test_no_newline_before_end_of_chunk() {
let input = "diff --git a/plugins/review/plugin.kdl b/plugins/review/plugin.kdl\nindex 83f0355..9fa8e47 100644\n--- a/plugins/review/plugin.kdl\n+++ b/plugins/review/plugin.kdl\n@@ -6,4 +6,4 @@ entrypoint {\n- on arch=\"aarch64-apple-darwin\" \"./hc-mitre-review\"\n- on arch=\"x86_64-apple-darwin\" \"./hc-mitre-review\"\n- on arch=\"x86_64-unknown-linux-gnu\" \"./hc-mitre-review\"\n- on arch=\"x86_64-pc-windows-msvc\" \"./hc-mitre-review\"\n+ on arch=\"aarch64-apple-darwin\" \"./target/debug/review_sdk\"\n+ on arch=\"x86_64-apple-darwin\" \"./target/debug/review_sdk\"\n+ on arch=\"x86_64-unknown-linux-gnu\" \"./target/debug/review_sdk\"\n+ on arch=\"x86_64-pc-windows-msvc\" \"./target/debug/review_sdk\"\n@@ -14 +14 @@ dependencies {\n-}\n\\ No newline at end of file\n+}\n";

let (leftover, _parsed) = crate::parse::patch(input).unwrap();
assert!(leftover.is_empty());
}
}
16 changes: 10 additions & 6 deletions plugins/git/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,20 +265,24 @@ fn patch_header(input: &str) -> IResult<&str, &str> {
recognize(tuple((metas, line, line)))(input)
}

fn plus_or_minus(input: &str) -> IResult<&str, &str> {
recognize(one_of("+-"))(input)
fn chunk_prefix(input: &str) -> IResult<&str, &str> {
recognize(one_of("+-\\"))(input)
}

fn line_with_ending(input: &str) -> IResult<&str, &str> {
recognize(tuple((not_line_ending, line_ending)))(input)
}

fn chunk_line(input: &str) -> IResult<&str, &str> {
preceded(plus_or_minus, line_with_ending)(input)
preceded(chunk_prefix, line_with_ending)(input)
}

fn chunk_body(input: &str) -> IResult<&str, String> {
fold_many0(chunk_line, String::new, |mut patch, line| {
if line == " No newline at end of file\n" {
return patch;
}

patch.push_str(line);
patch
})(input)
Expand Down Expand Up @@ -307,7 +311,7 @@ fn patch_footer(input: &str) -> IResult<&str, Option<&str>> {
opt(no_newline)(input)
}

fn patch(input: &str) -> IResult<&str, String> {
pub(crate) fn patch(input: &str) -> IResult<&str, String> {
tuple((patch_header, chunks, patch_footer))(input).map(|(i, (_, chunks, _))| (i, chunks))
}

Expand Down Expand Up @@ -612,13 +616,13 @@ use serde::{Serialize, Deserialize};\n";
let input_plus = "+";
let expected_plus = "+";

let (remaining, c) = plus_or_minus(input_plus).unwrap();
let (remaining, c) = chunk_prefix(input_plus).unwrap();
assert_eq!("", remaining);
assert_eq!(expected_plus, c);

let input_minus = "-";
let expected_minus = "-";
let (remaining, c) = plus_or_minus(input_minus).unwrap();
let (remaining, c) = chunk_prefix(input_minus).unwrap();
assert_eq!("", remaining);
assert_eq!(expected_minus, c);
}
Expand Down

0 comments on commit de67bed

Please sign in to comment.