use super::types::TraceVcs;
use std::path::Path;
use std::process::Command;
pub fn get_vcs_context(cwd: &str) -> Option<TraceVcs> {
let cwd_path = Path::new(cwd);
if !is_git_repo(cwd_path) {
return None;
}
let revision = get_git_revision(cwd_path);
let branch = get_git_branch(cwd_path);
let repo_root = get_git_repo_root(cwd_path);
if revision.is_some() || branch.is_some() || repo_root.is_some() {
Some(TraceVcs {
revision,
branch,
repo_root,
})
} else {
None
}
}
pub fn get_vcs_context_light(cwd: &str) -> Option<TraceVcs> {
let cwd_path = Path::new(cwd);
let branch = get_git_branch(cwd_path)?;
Some(TraceVcs {
revision: None,
branch: Some(branch),
repo_root: None,
})
}
fn is_git_repo(cwd: &Path) -> bool {
Command::new("git")
.args(["rev-parse", "--git-dir"])
.current_dir(cwd)
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
fn get_git_revision(cwd: &Path) -> Option<String> {
Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(cwd)
.output()
.ok()
.filter(|o| o.status.success())
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
.filter(|s| !s.is_empty())
}
fn get_git_branch(cwd: &Path) -> Option<String> {
let output = Command::new("git")
.args(["rev-parse", "--abbrev-ref", "HEAD"])
.current_dir(cwd)
.output()
.ok()?;
if !output.status.success() {
return None;
}
let branch = String::from_utf8_lossy(&output.stdout).trim().to_string();
if branch.is_empty() || branch == "HEAD" {
None
} else {
Some(branch)
}
}
fn get_git_repo_root(cwd: &Path) -> Option<String> {
Command::new("git")
.args(["rev-parse", "--show-toplevel"])
.current_dir(cwd)
.output()
.ok()
.filter(|o| o.status.success())
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
.filter(|s| !s.is_empty())
}