use std::path::Path;
use anyhow::Result;
use swiftide::{traits::Command, traits::ToolExecutor};
use crate::util::accept_non_zero_exit;
pub async fn diff(executor: &dyn ToolExecutor, base_sha: &str, color: bool) -> Result<String> {
let color = if color { "--color=always" } else { "" };
let cmd = Command::shell(format!("git diff {color} {base_sha}",));
let mut output = accept_non_zero_exit(executor.exec_cmd(&cmd).await)?.output;
if output.is_empty() {
output = "No changes".to_string();
}
Ok(output)
}
pub fn main_branch(workdir: impl AsRef<Path>) -> String {
const DEFAULT_BRANCH: &str = "main";
const MAIN_BRANCH_CMD: &str = "(git symbolic-ref refs/remotes/origin/HEAD >/dev/null 2>&1 || git remote set-head origin --auto >/dev/null 2>&1) && git rev-parse --abbrev-ref origin/HEAD";
let Ok(output) = std::process::Command::new("sh")
.arg("-c")
.arg(MAIN_BRANCH_CMD)
.current_dir(workdir.as_ref())
.output()
else {
return DEFAULT_BRANCH.to_string();
};
let parsed = std::str::from_utf8(&output.stdout)
.unwrap_or(DEFAULT_BRANCH)
.trim_start_matches("origin/")
.trim();
if parsed.is_empty() {
DEFAULT_BRANCH.to_string()
} else {
parsed.to_string()
}
}
pub async fn is_dirty(workdir: impl AsRef<Path>) -> bool {
tokio::process::Command::new("git")
.arg("diff-index")
.arg("--quiet")
.arg("HEAD")
.current_dir(workdir.as_ref())
.output()
.await
.map(|output| !output.status.success())
.unwrap_or(true)
}