use std::path::{Path, PathBuf};
pub fn branch(cwd: &Path) -> Option<String> {
let git_dir = find_git_dir(cwd)?;
let head = std::fs::read_to_string(git_dir.join("HEAD")).ok()?;
let head = head.trim();
if let Some(reference) = head.strip_prefix("ref: ") {
let name = reference.strip_prefix("refs/heads/").unwrap_or(reference);
return Some(name.to_string());
}
if head.is_empty() {
return None;
}
Some(head.chars().take(8).collect())
}
fn find_git_dir(cwd: &Path) -> Option<PathBuf> {
let mut dir = cwd;
loop {
let candidate = dir.join(".git");
if candidate.is_dir() {
return Some(candidate);
}
if candidate.is_file() {
let text = std::fs::read_to_string(&candidate).ok()?;
let target = text.trim().strip_prefix("gitdir:")?.trim();
let target = PathBuf::from(target);
return Some(if target.is_absolute() {
target
} else {
dir.join(target)
});
}
dir = dir.parent()?;
}
}
#[cfg(test)]
#[path = "git_tests.rs"]
mod tests;