use anyhow::{Context, Result};
use std::path::PathBuf;
use std::process::Command;
pub(crate) fn find_repo_root() -> Result<PathBuf> {
let mut dir = std::env::current_dir().context("Failed to get current directory")?;
loop {
if dir.join(".git").exists() {
return Ok(dir);
}
let Some(parent) = dir.parent() else {
anyhow::bail!("Not inside a git repository");
};
dir = parent.to_path_buf();
}
}
pub(crate) fn confirm(prompt: &str, yes: bool) -> bool {
if yes {
return true;
}
eprint!("{} [y/N] ", prompt);
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap_or(0);
matches!(input.trim(), "y" | "Y")
}
pub(crate) fn git_config_get(key: &str, scope: &str) -> Option<String> {
let output = Command::new("git")
.args(["config", scope, "--get", key])
.output()
.ok()?;
if output.status.success() {
Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn find_repo_root_finds_git_dir() {
let dir = TempDir::new().unwrap();
std::fs::create_dir(dir.path().join(".git")).unwrap();
let subdir = dir.path().join("src");
std::fs::create_dir(&subdir).unwrap();
assert!(dir.path().join(".git").exists());
}
#[test]
fn confirm_returns_true_when_yes_flag_set() {
assert!(confirm("anything?", true));
}
#[test]
fn git_config_get_returns_none_for_missing_key() {
let result = git_config_get("nonexistent.key.xyz", "--global");
assert!(result.is_none());
}
}