bricks/libs/
git_utils.rs

1use anyhow::{bail, Result};
2use git2::Oid;
3
4pub trait RepositoryExt {
5    fn resolve_commit(&self, version: &str) -> Result<Oid>;
6    fn checkout(&self, version: &str) -> Result<()>;
7    fn fetch_all(&self, repo_uri: &str) -> Result<()>;
8}
9
10impl RepositoryExt for git2::Repository {
11    fn resolve_commit(&self, version: &str) -> Result<Oid> {
12        let rev = self.revparse_single(version)?;
13
14        match rev.kind() {
15            Some(git2::ObjectType::Commit) => Ok(rev.id()),
16            Some(git2::ObjectType::Any) => bail!("`version` must resolve to a commit, got `Any`"),
17            Some(git2::ObjectType::Tree) => bail!("`version` must resolve to a commit, got `Tree`"),
18            Some(git2::ObjectType::Blob) => bail!("`version` must resolve to a commit, got `Blob`"),
19            Some(git2::ObjectType::Tag) => bail!("`version` must resolve to a commit, got `Tag`"),
20            None => bail!("no rev found for `version` {}", version),
21        }
22    }
23    fn checkout(&self, version: &str) -> Result<()> {
24        let obj = self.revparse_single(version)?;
25        let commit = obj.peel_to_commit()?;
26        self.checkout_tree(
27            commit.as_object(),
28            Some(git2::build::CheckoutBuilder::new().force()),
29        )?;
30        self.set_head_detached(commit.id())?;
31        Ok(())
32    }
33
34    fn fetch_all(&self, repo_uri: &str) -> Result<()> {
35        let mut remote = self.remote_anonymous(repo_uri)?;
36        Ok(remote.fetch(&["+refs/heads/*:refs/remotes/temp/*"], None, None)?)
37    }
38}