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