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