use std::path::Path;
use anyhow::Result;
use swiftide_core::{Command, ToolExecutor};
use crate::util::accept_non_zero_exit;
pub async fn diff(executor: &dyn ToolExecutor, base_sha: &str) -> Result<String> {
let cmd = Command::shell(format!("git diff --color=always {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)
}