use std::path::{Path, PathBuf};
pub mod amendment;
pub mod commit;
pub mod diff_split;
pub mod main_branches;
pub mod remote;
pub mod repository;
pub mod worktree_rebase;
pub use amendment::AmendmentHandler;
pub use commit::{
refine_message_scope, resolve_scope, CommitAnalysis, CommitAnalysisForAI, CommitInfo,
CommitInfoForAI, FileDiffRef,
};
pub use diff_split::{split_by_file, split_file_by_hunk, FileDiff, HunkDiff};
pub use main_branches::{branches_containing, detect_main_branch_tips, MainBranchTip};
pub use remote::RemoteInfo;
pub use repository::GitRepository;
pub const SHORT_HASH_LEN: usize = 8;
pub const FULL_HASH_LEN: usize = 40;
const GIT_BIN_ENV: &str = "OMNI_DEV_GIT_BIN";
const GIT_BINARY_CANDIDATES: &[&str] = &[
"/opt/homebrew/bin/git",
"/usr/local/bin/git",
"/home/linuxbrew/.linuxbrew/bin/git",
"/usr/bin/git",
];
#[must_use]
pub fn resolve_git_binary() -> PathBuf {
resolve_git_binary_from(std::env::var_os(GIT_BIN_ENV), GIT_BINARY_CANDIDATES)
}
fn resolve_git_binary_from(
env_override: Option<std::ffi::OsString>,
candidates: &[&str],
) -> PathBuf {
if let Some(path) = env_override.filter(|p| !p.is_empty()) {
return PathBuf::from(path);
}
for candidate in candidates {
let path = Path::new(candidate);
if path.exists() {
return path.to_path_buf();
}
}
PathBuf::from("git")
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn resolve_git_binary_from_prefers_env_then_candidate_then_fallback() {
assert_eq!(
resolve_git_binary_from(Some("/custom/git".into()), &["/usr/bin/git"]),
PathBuf::from("/custom/git"),
"an explicit override wins over every candidate"
);
let existing = std::env::current_exe().unwrap();
let existing = existing.to_str().unwrap();
assert_eq!(
resolve_git_binary_from(None, &["/no/such/git/xyzzy", existing]),
PathBuf::from(existing),
"the first *existing* candidate wins, not merely the first"
);
assert_eq!(
resolve_git_binary_from(None, &["/no/such/git/xyzzy"]),
PathBuf::from("git"),
"with nothing found, fall back to a bare PATH lookup"
);
assert_eq!(
resolve_git_binary_from(Some(String::new().into()), &["/no/such/git/xyzzy"]),
PathBuf::from("git"),
"an empty override is ignored rather than spawning \"\""
);
}
#[test]
fn resolve_git_binary_reads_the_real_environment() {
let _ = resolve_git_binary();
}
}