Skip to main content

radicle_surf/
revision.rs

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/// The signature of a commit
9#[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
18/// Supports various ways to specify a revision used in Git.
19pub trait Revision {
20    type Error: std::error::Error + Send + Sync + 'static;
21
22    /// Returns the object id of this revision in `repo`.
23    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        // TODO: Support for SHA-256.
57        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
102/// A common trait for anything that can convert to a `Commit`.
103pub trait ToCommit {
104    type Error: std::error::Error + Send + Sync + 'static;
105
106    /// Converts to a commit in `repo`.
107    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}