fix: introduce ExtractHeredocError that implements PartialEq (#958)

This commit is contained in:
Michael Bolin
2025-05-16 09:42:27 -07:00
committed by GitHub
parent 84e01f4b62
commit 3d9f4fcd8a
2 changed files with 24 additions and 32 deletions

View File

@@ -4,9 +4,9 @@ mod seek_sequence;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
use std::str::Utf8Error;
use anyhow::Context;
use anyhow::Error;
use anyhow::Result;
pub use parser::Hunk;
pub use parser::ParseError;
@@ -15,6 +15,7 @@ use parser::UpdateFileChunk;
pub use parser::parse_patch;
use similar::TextDiff;
use thiserror::Error;
use tree_sitter::LanguageError;
use tree_sitter::Parser;
use tree_sitter_bash::LANGUAGE as BASH;
@@ -52,10 +53,10 @@ impl PartialEq for IoError {
}
}
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub enum MaybeApplyPatch {
Body(Vec<Hunk>),
ShellParseError(Error),
ShellParseError(ExtractHeredocError),
PatchParseError(ParseError),
NotApplyPatch,
}
@@ -97,14 +98,14 @@ pub enum ApplyPatchFileChange {
},
}
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub enum MaybeApplyPatchVerified {
/// `argv` corresponded to an `apply_patch` invocation, and these are the
/// resulting proposed file changes.
Body(ApplyPatchAction),
/// `argv` could not be parsed to determine whether it corresponds to an
/// `apply_patch` invocation.
ShellParseError(Error),
ShellParseError(ExtractHeredocError),
/// `argv` corresponded to an `apply_patch` invocation, but it could not
/// be fulfilled due to the specified error.
CorrectnessError(ApplyPatchError),
@@ -112,26 +113,6 @@ pub enum MaybeApplyPatchVerified {
NotApplyPatch,
}
impl PartialEq for MaybeApplyPatchVerified {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(MaybeApplyPatchVerified::Body(a), MaybeApplyPatchVerified::Body(b)) => a == b,
(
MaybeApplyPatchVerified::ShellParseError(a),
MaybeApplyPatchVerified::ShellParseError(b),
) => a.to_string() == b.to_string(),
(
MaybeApplyPatchVerified::CorrectnessError(a),
MaybeApplyPatchVerified::CorrectnessError(b),
) => a == b,
(MaybeApplyPatchVerified::NotApplyPatch, MaybeApplyPatchVerified::NotApplyPatch) => {
true
}
_ => false,
}
}
}
#[derive(Debug, PartialEq)]
/// ApplyPatchAction is the result of parsing an `apply_patch` command. By
/// construction, all paths should be absolute paths.
@@ -225,19 +206,21 @@ pub fn maybe_parse_apply_patch_verified(argv: &[String], cwd: &Path) -> MaybeApp
/// * `Ok(String)` - The heredoc body if the extraction is successful.
/// * `Err(anyhow::Error)` - An error if the extraction fails.
///
fn extract_heredoc_body_from_apply_patch_command(src: &str) -> anyhow::Result<String> {
fn extract_heredoc_body_from_apply_patch_command(
src: &str,
) -> std::result::Result<String, ExtractHeredocError> {
if !src.trim_start().starts_with("apply_patch") {
anyhow::bail!("expected command to start with 'apply_patch'");
return Err(ExtractHeredocError::CommandDidNotStartWithApplyPatch);
}
let lang = BASH.into();
let mut parser = Parser::new();
parser
.set_language(&lang)
.context("failed to load bash grammar")?;
.map_err(ExtractHeredocError::FailedToLoadBashGrammar)?;
let tree = parser
.parse(src, None)
.ok_or_else(|| anyhow::anyhow!("failed to parse patch into AST"))?;
.ok_or(ExtractHeredocError::FailedToParsePatchIntoAst)?;
let bytes = src.as_bytes();
let mut c = tree.root_node().walk();
@@ -247,7 +230,7 @@ fn extract_heredoc_body_from_apply_patch_command(src: &str) -> anyhow::Result<St
if node.kind() == "heredoc_body" {
let text = node
.utf8_text(bytes)
.context("failed to interpret heredoc body as UTF-8")?;
.map_err(ExtractHeredocError::HeredocNotUtf8)?;
return Ok(text.trim_end_matches('\n').to_owned());
}
@@ -256,12 +239,21 @@ fn extract_heredoc_body_from_apply_patch_command(src: &str) -> anyhow::Result<St
}
while !c.goto_next_sibling() {
if !c.goto_parent() {
anyhow::bail!("expected to find heredoc_body in patch candidate");
return Err(ExtractHeredocError::FailedToFindHeredocBody);
}
}
}
}
#[derive(Debug, PartialEq)]
pub enum ExtractHeredocError {
CommandDidNotStartWithApplyPatch,
FailedToLoadBashGrammar(LanguageError),
HeredocNotUtf8(Utf8Error),
FailedToParsePatchIntoAst,
FailedToFindHeredocBody,
}
/// Applies the patch and prints the result to stdout/stderr.
pub fn apply_patch(
patch: &str,

View File

@@ -1080,7 +1080,7 @@ async fn handle_function_call(
};
}
MaybeApplyPatchVerified::ShellParseError(error) => {
trace!("Failed to parse shell command, {error}");
trace!("Failed to parse shell command, {error:?}");
}
MaybeApplyPatchVerified::NotApplyPatch => (),
}