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