1#![forbid(unsafe_code)]
9
10pub use crate::describe::*;
11pub use crate::error::Error;
12use git2::{Branch, BranchType, Commit, Repository};
13use std::path::Path;
14
15mod describe;
16mod error;
17
18pub fn discover_repository<T: AsRef<Path>>(directory: T) -> Result<Repository, Error> {
21 let starting_point = directory.as_ref();
22 Repository::discover(starting_point).map_err(|_e| Error::Discovery {
23 path: starting_point.display().to_string(),
24 })
25}
26pub fn git_repodir_for_repo(repo: Repository) -> Result<Repository, Error> {
30 if repo.is_worktree() {
31 let repo_path = repo.path();
32 return Repository::open(repo_path).map_err(|_e| Error::Worktree {
33 path: repo_path.display().to_string(),
34 });
35 }
36 Ok(repo)
37}
38
39pub fn discover_repo_or_worktree_at<T: AsRef<Path>>(directory: T) -> Result<Repository, Error> {
43 let repo = discover_repository(directory)?;
44 let repo = git_repodir_for_repo(repo)?;
45 Ok(repo)
46}
47
48pub fn get_head_for_repo(repo: &Repository) -> Result<Commit, Error> {
52 let Ok(head) = repo.head() else {
53 return Error::head(repo.path());
54 };
55 head.peel_to_commit()
56 .map_err(|_| Error::ref_not_in_repo(repo, &head))
57}
58
59pub fn get_branch_for_head(repo: &Repository) -> Result<Branch, Error> {
62 let Ok(reference) = repo.head() else {
63 return Error::head(repo.path());
64 };
65 let name = String::from_utf8_lossy(reference.shorthand_bytes()).to_string();
66
67 let Ok(branch) = repo.find_branch(&name, BranchType::Local) else {
68 return Error::branch_err(repo, &name);
69 };
70 Ok(branch)
71}