use std::path::Path;
use std::process::Command;
pub fn git_last_commit_hash(root: &Path, file: &str) -> Option<String> {
let output = Command::new("git")
.args(["log", "-1", "--format=%H", "--", file])
.current_dir(root)
.output()
.ok()?;
let hash = String::from_utf8_lossy(&output.stdout).trim().to_string();
if hash.is_empty() { None } else { Some(hash) }
}
pub fn git_commits_between(root: &Path, spec_file: &str, source_file: &str) -> usize {
let spec_commit = match git_last_commit_hash(root, spec_file) {
Some(h) => h,
None => return 0,
};
let output = match Command::new("git")
.args([
"rev-list",
"--count",
&format!("{spec_commit}..HEAD"),
"--",
source_file,
])
.current_dir(root)
.output()
{
Ok(o) => o,
Err(_) => return 0,
};
String::from_utf8_lossy(&output.stdout)
.trim()
.parse::<usize>()
.unwrap_or(0)
}
pub fn is_git_repo(root: &Path) -> bool {
Command::new("git")
.args(["rev-parse", "--is-inside-work-tree"])
.current_dir(root)
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
#[derive(Debug, Clone)]
pub struct StaleInfo {
pub spec_path: String,
pub module_name: String,
pub max_commits_behind: usize,
pub source_details: Vec<(String, usize)>,
}