1use crate::branch::Branch;
4use git2::{self, Oid};
5use std::{fmt, sync::Arc};
6
7pub type GitResult<T> = Result<T, GitError>;
8
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct HashId(String);
12
13impl fmt::Display for HashId {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 write!(f, "{}", self.0)
16 }
17}
18
19impl HashId {
20 pub fn to_oid(&self) -> Oid {
21 self.clone().into()
22 }
23
24 pub fn to_string(&self) -> String {
25 self.0.clone()
26 }
27}
28
29impl From<Oid> for HashId {
30 fn from(o: Oid) -> Self {
31 Self(o.to_string())
32 }
33}
34
35impl From<HashId> for Oid {
36 fn from(hid: HashId) -> Self {
37 Oid::from_str(hid.0.as_str()).expect(&format!(
38 "Tried turning an invalid HashId variant into an Oid: {:?}",
39 hid
40 ))
41 }
42}
43
44impl<'any> From<&'any HashId> for Oid {
45 fn from(hid: &'any HashId) -> Self {
46 Oid::from_str(hid.0.as_str()).expect(&format!(
47 "Tried turning an invalid HashId variant into an Oid: {:?}",
48 hid
49 ))
50 }
51}
52
53#[derive(Debug)]
55pub enum GitError {
56 AllBad,
57}
58
59impl From<git2::Error> for GitError {
60 fn from(_: git2::Error) -> Self {
61 Self::AllBad
62 }
63}
64
65#[derive(Clone)]
67pub struct Repository {
68 inner: Arc<git2::Repository>,
69}
70
71impl Repository {
72 pub fn open(path: &str) -> GitResult<Self> {
74 Ok(Self {
75 inner: Arc::new(git2::Repository::open(path)?),
76 })
77 }
78
79 pub fn branches(&self) -> GitResult<Vec<Branch>> {
88 Ok(self
89 .inner
90 .branches(None)?
91 .into_iter()
92 .filter_map(|e| e.ok())
93 .map(|(branch, _)| {
94 let name = branch.name().unwrap().unwrap().into();
95 let head = branch.get().peel_to_commit().unwrap().id().into();
96 Branch::new(&self.inner, name, head)
97 })
98 .collect())
99 }
100
101 pub fn branch(&self, name: String) -> Option<Branch> {
108 self.branches().ok().and_then(|ok| {
109 ok.into_iter()
110 .filter(|b| b.name().is_some())
111 .find(|b| &b.name().unwrap() == &name)
112 })
113 }
114}