radicle_cob/object/
storage.rs1use std::{collections::BTreeMap, error::Error};
4
5use git_ext::ref_format::RefString;
6use git_ext::Oid;
7use radicle_crypto::PublicKey;
8
9use crate::change::EntryId;
10use crate::{ObjectId, TypeName};
11
12#[derive(Clone, Debug, Default)]
15pub struct Objects(Vec<Reference>);
16
17impl Objects {
18 pub fn new(reference: Reference) -> Self {
19 Self(vec![reference])
20 }
21
22 pub fn push(&mut self, reference: Reference) {
23 self.0.push(reference)
24 }
25
26 pub fn iter(&self) -> impl Iterator<Item = &Reference> {
29 self.0.iter()
30 }
31}
32
33impl From<Vec<Reference>> for Objects {
34 fn from(refs: Vec<Reference>) -> Self {
35 Objects(refs)
36 }
37}
38
39#[derive(Clone, Debug)]
42pub struct Reference {
43 pub name: RefString,
45 pub target: Commit,
47}
48
49#[derive(Clone, Debug)]
51pub struct Commit {
52 pub id: Oid,
54}
55
56pub trait Storage {
57 type ObjectsError: Error + Send + Sync + 'static;
58 type TypesError: Error + Send + Sync + 'static;
59 type UpdateError: Error + Send + Sync + 'static;
60 type RemoveError: Error + Send + Sync + 'static;
61
62 fn objects(
65 &self,
66 typename: &TypeName,
67 object_id: &ObjectId,
68 ) -> Result<Objects, Self::ObjectsError>;
69
70 fn types(&self, typename: &TypeName) -> Result<BTreeMap<ObjectId, Objects>, Self::TypesError>;
73
74 fn update(
76 &self,
77 identifier: &PublicKey,
78 typename: &TypeName,
79 object_id: &ObjectId,
80 entry: &EntryId,
81 ) -> Result<(), Self::UpdateError>;
82
83 fn remove(
85 &self,
86 identifier: &PublicKey,
87 typename: &TypeName,
88 object_id: &ObjectId,
89 ) -> Result<(), Self::RemoveError>;
90}
91
92pub mod convert {
93 use std::str;
94
95 use git_ext::ref_format::RefString;
96 use thiserror::Error;
97
98 use super::{Commit, Reference};
99
100 #[derive(Debug, Error)]
101 pub enum Error {
102 #[error("the reference '{name}' does not point to a commit object")]
103 NotCommit {
104 name: RefString,
105 #[source]
106 err: git2::Error,
107 },
108 #[error(transparent)]
109 Ref(#[from] git_ext::ref_format::Error),
110 #[error(transparent)]
111 Utf8(#[from] str::Utf8Error),
112 }
113
114 impl<'a> TryFrom<git2::Reference<'a>> for Reference {
115 type Error = Error;
116
117 fn try_from(value: git2::Reference<'a>) -> Result<Self, Self::Error> {
118 let name = RefString::try_from(str::from_utf8(value.name_bytes())?)?;
119 let target = Commit::from(value.peel_to_commit().map_err(|err| Error::NotCommit {
120 name: name.clone(),
121 err,
122 })?);
123 Ok(Self { name, target })
124 }
125 }
126
127 impl<'a> From<git2::Commit<'a>> for Commit {
128 fn from(commit: git2::Commit<'a>) -> Self {
129 Commit {
130 id: commit.id().into(),
131 }
132 }
133 }
134}