1use std::{convert::Infallible, str::FromStr};
2
3use git_ext::{
4 ref_format::{Qualified, RefString},
5 Oid,
6};
7
8use crate::{Branch, Commit, Error, Repository, Tag};
9
10#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
12pub struct Signature(Vec<u8>);
13
14impl From<git2::Buf> for Signature {
15 fn from(other: git2::Buf) -> Self {
16 Signature((*other).into())
17 }
18}
19
20pub trait Revision {
22 type Error: std::error::Error + Send + Sync + 'static;
23
24 fn object_id(&self, repo: &Repository) -> Result<Oid, Self::Error>;
26}
27
28impl Revision for RefString {
29 type Error = git2::Error;
30
31 fn object_id(&self, repo: &Repository) -> Result<Oid, Self::Error> {
32 repo.refname_to_id(self)
33 }
34}
35
36impl Revision for Qualified<'_> {
37 type Error = git2::Error;
38
39 fn object_id(&self, repo: &Repository) -> Result<Oid, Self::Error> {
40 repo.refname_to_id(self)
41 }
42}
43
44impl Revision for Oid {
45 type Error = Infallible;
46
47 fn object_id(&self, _repo: &Repository) -> Result<Oid, Self::Error> {
48 Ok(*self)
49 }
50}
51
52impl Revision for &str {
53 type Error = git2::Error;
54
55 fn object_id(&self, _repo: &Repository) -> Result<Oid, Self::Error> {
56 Oid::from_str(self)
57 }
58}
59
60impl Revision for Branch {
61 type Error = Error;
62
63 fn object_id(&self, repo: &Repository) -> Result<Oid, Self::Error> {
64 let refname = repo.namespaced_refname(&self.refname())?;
65 Ok(repo.refname_to_id(&refname)?)
66 }
67}
68
69impl Revision for Tag {
70 type Error = Infallible;
71
72 fn object_id(&self, _repo: &Repository) -> Result<Oid, Self::Error> {
73 Ok(self.id())
74 }
75}
76
77impl Revision for String {
78 type Error = git2::Error;
79
80 fn object_id(&self, _repo: &Repository) -> Result<Oid, Self::Error> {
81 Oid::from_str(self)
82 }
83}
84
85impl<R: Revision> Revision for &R {
86 type Error = R::Error;
87
88 fn object_id(&self, repo: &Repository) -> Result<Oid, Self::Error> {
89 (*self).object_id(repo)
90 }
91}
92
93impl<R: Revision> Revision for Box<R> {
94 type Error = R::Error;
95
96 fn object_id(&self, repo: &Repository) -> Result<Oid, Self::Error> {
97 self.as_ref().object_id(repo)
98 }
99}
100
101pub trait ToCommit {
103 type Error: std::error::Error + Send + Sync + 'static;
104
105 fn to_commit(self, repo: &Repository) -> Result<Commit, Self::Error>;
107}
108
109impl ToCommit for Commit {
110 type Error = Infallible;
111
112 fn to_commit(self, _repo: &Repository) -> Result<Commit, Self::Error> {
113 Ok(self)
114 }
115}
116
117impl<R: Revision> ToCommit for R {
118 type Error = Error;
119
120 fn to_commit(self, repo: &Repository) -> Result<Commit, Self::Error> {
121 let oid = repo.object_id(&self)?;
122 let commit = repo.find_commit(oid)?;
123 Ok(Commit::try_from(commit)?)
124 }
125}