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}