use anyhow::bail;
use serde::{Deserialize, Serialize};
use smart_patcher::PatchFile;
use std::path::PathBuf;
use crate::entities::environment::RunEnvironment;
#[derive(Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Default, Clone)]
pub struct PatchAction {
pub patch: PathBuf,
#[serde(skip_serializing_if = "Option::is_none")]
pub ignore_fails: Option<bool>,
}
impl PatchAction {
pub async fn execute(&self, env: &RunEnvironment<'_>) -> anyhow::Result<(bool, Vec<String>)> {
let patch_file = env.run_dir.join(&self.patch);
let file = std::fs::File::open(patch_file)?;
let buf = std::io::BufReader::new(file);
let patches: PatchFile = serde_json::from_reader(buf)?;
match patches.patch(env.run_dir, env.run_dir) {
Err(e) => Ok((false, vec![format!("Patch application failed: {e}")])),
Ok(0) if self.ignore_fails.is_none_or(|v| !v) => Ok((false, vec!["The patch wasn't applied! The contents of the patch are probably incorrect, or the project files have changed.".to_string()])),
Ok(num) => Ok((
true,
vec![format!("The patch has been applied {num} time(s).")],
)),
}
}
pub async fn test(&self, env: &RunEnvironment<'_>) -> anyhow::Result<(bool, Vec<String>)> {
let patch_file = env.run_dir.join(&self.patch);
let file = std::fs::File::open(patch_file)?;
let buf = std::io::BufReader::new(file);
let patches: PatchFile = serde_json::from_reader(buf)?;
match patches.test(env.run_dir, env.run_dir) {
Err(e) => Ok((false, vec![format!("Patch test failed: {e}")])),
Ok(0) if self.ignore_fails.is_none_or(|v| !v) => Ok((false, vec!["The patch can't be applied! The contents of the patch are probably incorrect, or the project files have changed.".to_string()])),
Ok(num) => Ok((
true,
vec![format!("The patch can be applied {num} time(s).")],
)),
}
}
pub async fn to_shell(&self, _: &RunEnvironment<'_>) -> anyhow::Result<Vec<String>> {
bail!("`Patch` actions can't be translated into shell script!")
}
}