radicle_surf/
revision.rs

1// This file is part of radicle-surf
2// <https://github.com/radicle-dev/radicle-surf>
3//
4// Copyright (C) 2019-2020 The Radicle Team <dev@radicle.xyz>
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License version 3 or
8// later as published by the Free Software Foundation.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18use 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/// The signature of a commit
28#[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
37/// Supports various ways to specify a revision used in Git.
38pub trait Revision {
39    type Error: std::error::Error + Send + Sync + 'static;
40
41    /// Returns the object id of this revision in `repo`.
42    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
118/// A common trait for anything that can convert to a `Commit`.
119pub trait ToCommit {
120    type Error: std::error::Error + Send + Sync + 'static;
121
122    /// Converts to a commit in `repo`.
123    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}