use std::process::Command;
#[derive(Debug, Clone)]
pub struct GitPhaseDirtyConfig {
pub commit_message: String,
}
impl Default for GitPhaseDirtyConfig {
fn default() -> Self {
Self { commit_message: "chore: auto-commit dirty tree".to_string() }
}
}
pub fn check_dirty() -> bool {
let output = Command::new("git").arg("status").arg("--porcelain").output();
match output {
Ok(out) => {
let status = String::from_utf8_lossy(&out.stdout);
!status.trim().is_empty()
}
Err(_) => false, }
}
pub fn execute(config: &GitPhaseDirtyConfig, apply: bool) -> Result<(), String> {
if !check_dirty() {
return Ok(()); }
if apply {
crate::autonomic::subprocess::run_with_timeout("git", &["add", "-A"], false)?;
crate::autonomic::subprocess::run_with_timeout(
"git",
&["commit", "-m", &config.commit_message],
false,
)
.map(|_| ())
} else {
eprintln!(
"[GitPhaseDirtyPolicy] Would run: git add -A && git commit -m '{}'",
config.commit_message
);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_git_phase_dirty_config_default() {
let config = GitPhaseDirtyConfig::default();
assert_eq!(config.commit_message, "chore: auto-commit dirty tree");
}
#[test]
fn test_check_dirty_no_git() {
let _result = check_dirty();
}
#[test]
fn test_execute_dry_run() {
let config = GitPhaseDirtyConfig::default();
let result = execute(&config, false);
assert!(result.is_ok());
}
}