use crate::{BranchInfo, CommitInfo, GitError, RepoStatus, Result};
use git2::Repository;
use std::path::{Path, PathBuf};
pub struct GitRepo {
inner: Repository,
path: PathBuf,
}
impl GitRepo {
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref().to_path_buf();
let inner = git2::Repository::open(&path)?;
Ok(Self { inner, path })
}
pub fn discover(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref();
let inner = git2::Repository::discover(path)
.map_err(|_| GitError::NotARepo(path.display().to_string()))?;
let work_dir = inner
.workdir()
.map(|p| p.to_path_buf())
.unwrap_or_else(|| path.to_path_buf());
Ok(Self {
inner,
path: work_dir,
})
}
pub fn path(&self) -> &Path {
&self.path
}
pub fn git_dir(&self) -> PathBuf {
self.inner.path().to_path_buf()
}
pub fn is_bare(&self) -> bool {
self.inner.is_bare()
}
pub fn status(&self) -> Result<RepoStatus> {
RepoStatus::collect(&self.inner, &self.path)
}
pub fn current_branch(&self) -> Result<Option<BranchInfo>> {
BranchInfo::current(&self.inner)
}
pub fn branches(&self) -> Result<Vec<BranchInfo>> {
BranchInfo::list(&self.inner)
}
pub fn recent_commits(&self, count: usize) -> Result<Vec<CommitInfo>> {
CommitInfo::recent(&self.inner, count)
}
pub fn is_dirty(&self) -> Result<bool> {
Ok(!self.status()?.is_clean())
}
pub fn head_commit(&self) -> Result<Option<CommitInfo>> {
CommitInfo::head(&self.inner)
}
pub fn inner(&self) -> &Repository {
&self.inner
}
}