vinxen_git/
repo.rs

1use crate::{BranchInfo, CommitInfo, GitError, RepoStatus, Result};
2use git2::Repository;
3use std::path::{Path, PathBuf};
4
5pub struct GitRepo {
6    inner: Repository,
7    path: PathBuf,
8}
9
10impl GitRepo {
11    pub fn open(path: impl AsRef<Path>) -> Result<Self> {
12        let path = path.as_ref().to_path_buf();
13        let inner = git2::Repository::open(&path)?;
14        Ok(Self { inner, path })
15    }
16
17    pub fn discover(path: impl AsRef<Path>) -> Result<Self> {
18        let path = path.as_ref();
19        let inner = git2::Repository::discover(path)
20            .map_err(|_| GitError::NotARepo(path.display().to_string()))?;
21        let work_dir = inner
22            .workdir()
23            .map(|p| p.to_path_buf())
24            .unwrap_or_else(|| path.to_path_buf());
25        Ok(Self {
26            inner,
27            path: work_dir,
28        })
29    }
30
31    pub fn path(&self) -> &Path {
32        &self.path
33    }
34
35    pub fn git_dir(&self) -> PathBuf {
36        self.inner.path().to_path_buf()
37    }
38
39    pub fn is_bare(&self) -> bool {
40        self.inner.is_bare()
41    }
42
43    pub fn status(&self) -> Result<RepoStatus> {
44        RepoStatus::collect(&self.inner, &self.path)
45    }
46
47    pub fn current_branch(&self) -> Result<Option<BranchInfo>> {
48        BranchInfo::current(&self.inner)
49    }
50
51    pub fn branches(&self) -> Result<Vec<BranchInfo>> {
52        BranchInfo::list(&self.inner)
53    }
54
55    pub fn recent_commits(&self, count: usize) -> Result<Vec<CommitInfo>> {
56        CommitInfo::recent(&self.inner, count)
57    }
58
59    pub fn is_dirty(&self) -> Result<bool> {
60        Ok(!self.status()?.is_clean())
61    }
62
63    pub fn head_commit(&self) -> Result<Option<CommitInfo>> {
64        CommitInfo::head(&self.inner)
65    }
66
67    pub fn inner(&self) -> &Repository {
68        &self.inner
69    }
70}