use std::path::{Path, PathBuf};
use std::process::Command;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CommitSummary {
pub sha: String,
pub subject: String,
}
pub fn resolve_source_repo() -> Option<PathBuf> {
if let Ok(env_dir) = std::env::var("OPENCRABS_SRC") {
let p = PathBuf::from(env_dir);
if p.join(".git").exists() {
return Some(p);
}
}
let cwd = std::env::current_dir().ok()?;
let cargo = cwd.join("Cargo.toml");
if cargo.exists()
&& let Ok(text) = std::fs::read_to_string(&cargo)
&& text.contains(r#"name = "opencrabs""#)
&& cwd.join(".git").exists()
{
return Some(cwd);
}
None
}
pub fn commits_matching_since(repo: &Path, since_iso: &str, term: &str) -> Vec<CommitSummary> {
let output = match Command::new("git")
.arg("-C")
.arg(repo)
.arg("log")
.arg(format!("--since={}", since_iso))
.arg("--grep")
.arg(term)
.arg("-i")
.arg("--no-merges")
.arg("--format=%H%x09%s")
.output()
{
Ok(o) => o,
Err(e) => {
tracing::debug!(
"rsi_git_history: git log failed in {}: {}",
repo.display(),
e
);
return Vec::new();
}
};
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
tracing::debug!(
"rsi_git_history: git log non-zero in {}: status={:?} stderr={}",
repo.display(),
output.status.code(),
stderr.trim()
);
return Vec::new();
}
let stdout = String::from_utf8_lossy(&output.stdout);
parse_git_log_output(&stdout)
}
pub(crate) fn parse_git_log_output(stdout: &str) -> Vec<CommitSummary> {
stdout
.lines()
.filter_map(|line| {
let (sha, subject) = line.split_once('\t')?;
let sha = sha.trim();
let subject = subject.trim();
if sha.is_empty() || subject.is_empty() {
return None;
}
Some(CommitSummary {
sha: sha.to_string(),
subject: subject.to_string(),
})
})
.collect()
}