use super::repo::git;
use std::path::Path;
use std::process::{Command, Stdio};
pub fn head(root: &Path) -> Option<String> {
let out = git(root, &["rev-parse", "HEAD"])?;
Some(String::from_utf8_lossy(&out).trim().to_string())
}
pub fn resolve(root: &Path, rev: &str) -> Option<String> {
let out = git(root, &["rev-parse", "--verify", "--quiet", &format!("{rev}^{{commit}}")])?;
let s = String::from_utf8_lossy(&out).trim().to_string();
if s.is_empty() { None } else { Some(s) }
}
const EMPTY_TREE: &str = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
pub fn parent_or_empty(root: &Path, sha: &str) -> String {
match resolve(root, &format!("{sha}^")) {
Some(_) => format!("{sha}^"),
None => EMPTY_TREE.to_string(),
}
}
pub fn commit_diff(root: &Path, sha: &str) -> String {
format!("{}..{sha}", parent_or_empty(root, sha))
}
pub fn commit_log(root: &Path, sha: &str) -> String {
match resolve(root, &format!("{sha}^")) {
Some(_) => format!("{sha}^..{sha}"),
None => sha.to_string(),
}
}
pub fn upstream(root: &Path) -> Option<String> {
let out = git(root, &["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"])?;
let s = String::from_utf8(out).ok()?.trim().to_string();
if s.is_empty() { None } else { Some(s) }
}
pub fn is_ancestor_of_head(root: &Path, rev: &str) -> Option<bool> {
let status = Command::new("git")
.arg("-C")
.arg(root)
.args(["merge-base", "--is-ancestor", rev, "HEAD"])
.stderr(Stdio::null())
.status()
.ok()?;
match status.code() {
Some(0) => Some(true),
Some(1) => Some(false),
_ => None,
}
}