Skip to main content

auths_cli/commands/
git_helpers.rs

1use anyhow::{Context, Result, anyhow};
2
3use crate::subprocess::{git_command, git_silent};
4
5/// Resolve a git ref to a full commit SHA.
6///
7/// Args:
8/// * `commit_ref`: A git ref (branch name, tag, SHA, HEAD, etc.).
9///
10/// Usage:
11/// ```ignore
12/// let sha = resolve_commit_sha("HEAD")?;
13/// let sha = resolve_commit_sha("v1.0.0")?;
14/// ```
15pub fn resolve_commit_sha(commit_ref: &str) -> Result<String> {
16    let output = git_command(&["rev-parse", commit_ref])
17        .output()
18        .context("Failed to resolve commit reference")?;
19
20    if !output.status.success() {
21        let stderr = String::from_utf8_lossy(&output.stderr).to_string();
22        let lower = stderr.to_lowercase();
23
24        if lower.contains("unknown revision") || lower.contains("bad revision") {
25            let hint = if commit_ref.contains('~') || commit_ref.contains('^') {
26                "This repository may not have enough commits. \
27                 Try `git log --oneline` to see available history."
28            } else {
29                "Verify the ref exists with `git branch -a` or `git tag -l`."
30            };
31            return Err(anyhow!(
32                "Cannot resolve '{}': {}\n\nHint: {}",
33                commit_ref,
34                stderr.trim(),
35                hint
36            ));
37        }
38
39        return Err(anyhow!(
40            "Invalid commit reference '{}': {}",
41            commit_ref,
42            stderr.trim()
43        ));
44    }
45
46    Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
47}
48
49/// Silently attempt to resolve HEAD to a full commit SHA.
50///
51/// Returns `None` if not in a git repo, no commits exist, or git is unavailable.
52///
53/// Usage:
54/// ```ignore
55/// let sha = resolve_head_silent(); // Some("abc123...") or None
56/// ```
57pub fn resolve_head_silent() -> Option<String> {
58    git_silent(&["rev-parse", "--verify", "--quiet", "HEAD"])
59}