fn get_git_diff(cli: &Cli) -> Result<String, String> {
let is_git_repo = Command::new("sh")
.arg("-c")
.arg("git rev-parse --is-inside-work-tree")
.output()
.map(|output| output.status.success())
.unwrap_or(false);
if !is_git_repo {
return Err("Current directory is not a git repository".to_string());
}
let status_output = Command::new("sh")
.arg("-c")
.arg("git status --porcelain")
.output()
.map_err(|e| format!("Failed to execute git status: {}", e))?;
let status = String::from_utf8_lossy(&status_output.stdout).to_string();
if cli.add && status.lines().any(|line| {
line.starts_with(" M") || line.starts_with("MM") || line.starts_with("??") }) {
let add_output = Command::new("sh")
.arg("-c")
.arg("git add .")
.output()
.map_err(|e| format!("Failed to execute git add: {}", e))?;
if !add_output.status.success() {
return Err(String::from_utf8_lossy(&add_output.stderr).to_string());
}
}
let diff_cmd = if cli.dry_run {
match Command::new("sh")
.arg("-c")
.arg("git diff --cached")
.output() {
Ok(output) if output.status.success() => {
let diff = String::from_utf8_lossy(&output.stdout).to_string();
if !diff.trim().is_empty() {
return Ok(diff);
}
"git diff"
},
_ => "git diff" }
} else {
"git diff --cached"
};
let diff_output = Command::new("sh")
.arg("-c")
.arg(diff_cmd)
.output()
.map_err(|e| format!("Failed to execute {}: {}", diff_cmd, e))?;
if !diff_output.status.success() {
return Err(format!("Git diff command failed: {}", String::from_utf8_lossy(&diff_output.stderr)));
}
let diff = String::from_utf8_lossy(&diff_output.stdout).to_string();
if diff.trim().is_empty() {
return Err("No changes to commit".to_string());
}
Ok(diff)
}