radicle-cob: simplify Objects and remove identifier

Objects does not need to be separated by `local` and `remotes`, it
uses `iter` internally, so all references are used regardless.

Simplify Objects by having it be a simple vector of references.

This also means that the `identifier` is not needed. This was only
required to identify the local reference, so it can now be removed.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
Fintan Halpenny 2022-11-08 13:52:00 +00:00
parent d6416c9be1
commit 0bd213d15a
No known key found for this signature in database
GPG Key ID: 2552FB6F64066CB7
8 changed files with 41 additions and 64 deletions

View File

@ -13,15 +13,11 @@ use super::error;
/// [`crate::Change`]s at content-addressable locations. Please see /// [`crate::Change`]s at content-addressable locations. Please see
/// [`Store`] for further information. /// [`Store`] for further information.
/// ///
/// The `identifier` is a unqiue id that is passed through to the
/// [`crate::object::Storage`].
///
/// The `typename` is the type of object to be found, while the /// The `typename` is the type of object to be found, while the
/// `object_id` is the identifier for the particular object under that /// `object_id` is the identifier for the particular object under that
/// type. /// type.
pub fn get<S>( pub fn get<S>(
storage: &S, storage: &S,
identifier: &S::Identifier,
typename: &TypeName, typename: &TypeName,
oid: &ObjectId, oid: &ObjectId,
) -> Result<Option<CollaborativeObject>, error::Retrieve> ) -> Result<Option<CollaborativeObject>, error::Retrieve>
@ -29,7 +25,7 @@ where
S: Store, S: Store,
{ {
let tip_refs = storage let tip_refs = storage
.objects(identifier, typename, oid) .objects(typename, oid)
.map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?; .map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?;
Ok(ChangeGraph::load(storage, tip_refs.iter(), typename, oid).map(|graph| graph.evaluate())) Ok(ChangeGraph::load(storage, tip_refs.iter(), typename, oid).map(|graph| graph.evaluate()))
} }

View File

@ -38,14 +38,10 @@ pub struct ChangeGraphInfo {
/// [`crate::Change`]s at content-addressable locations. Please see /// [`crate::Change`]s at content-addressable locations. Please see
/// [`Store`] for further information. /// [`Store`] for further information.
/// ///
/// The `resource` is the parent of this object, for example a
/// software project.
///
/// The `typename` is the type of object to be found, while the `oid` /// The `typename` is the type of object to be found, while the `oid`
/// is the identifier for the particular object under that type. /// is the identifier for the particular object under that type.
pub fn changegraph<S>( pub fn changegraph<S>(
storage: &S, storage: &S,
identifier: &S::Identifier,
typename: &TypeName, typename: &TypeName,
oid: &ObjectId, oid: &ObjectId,
) -> Result<Option<ChangeGraphInfo>, error::Retrieve> ) -> Result<Option<ChangeGraphInfo>, error::Retrieve>
@ -53,7 +49,7 @@ where
S: Store, S: Store,
{ {
let tip_refs = storage let tip_refs = storage
.objects(identifier, typename, oid) .objects(typename, oid)
.map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?; .map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?;
Ok( Ok(
ChangeGraph::load(storage, tip_refs.iter(), typename, oid).map(|graph| ChangeGraphInfo { ChangeGraph::load(storage, tip_refs.iter(), typename, oid).map(|graph| ChangeGraphInfo {

View File

@ -13,20 +13,16 @@ use super::error;
/// [`crate::Change`]s at content-addressable locations. Please see /// [`crate::Change`]s at content-addressable locations. Please see
/// [`Store`] for further information. /// [`Store`] for further information.
/// ///
/// The `identifier` is a unqiue id that is passed through to the
/// [`crate::object::Storage`].
///
/// The `typename` is the type of objects to listed. /// The `typename` is the type of objects to listed.
pub fn list<S>( pub fn list<S>(
storage: &S, storage: &S,
identifier: &S::Identifier,
typename: &TypeName, typename: &TypeName,
) -> Result<Vec<CollaborativeObject>, error::Retrieve> ) -> Result<Vec<CollaborativeObject>, error::Retrieve>
where where
S: Store, S: Store,
{ {
let references = storage let references = storage
.types(identifier, typename) .types(typename)
.map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?; .map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?;
log::trace!("loaded {} references", references.len()); log::trace!("loaded {} references", references.len());
let mut result = Vec::new(); let mut result = Vec::new();

View File

@ -76,7 +76,7 @@ where
}; };
let existing_refs = storage let existing_refs = storage
.objects(identifier, typename, &object_id) .objects(typename, &object_id)
.map_err(|err| error::Update::Refs { err: Box::new(err) })?; .map_err(|err| error::Update::Refs { err: Box::new(err) })?;
let mut object = ChangeGraph::load(storage, existing_refs.iter(), typename, &object_id) let mut object = ChangeGraph::load(storage, existing_refs.iter(), typename, &object_id)

View File

@ -14,20 +14,27 @@ use crate::{ObjectId, TypeName};
/// The [`Reference`]s that refer to the commits that make up a /// The [`Reference`]s that refer to the commits that make up a
/// [`crate::CollaborativeObject`]. /// [`crate::CollaborativeObject`].
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Objects { pub struct Objects(Vec<Reference>);
/// If the local peer has a [`Reference`] for this particular
/// object, then `local` should be set.
pub local: Option<Reference>,
/// The `remotes` are the entries for each remote peer's version
/// of the particular object.
pub remotes: Vec<Reference>,
}
impl Objects { impl Objects {
pub fn new(reference: Reference) -> Self {
Self(vec![reference])
}
pub fn push(&mut self, reference: Reference) {
self.0.push(reference)
}
/// Return an iterator over the `local` and `remotes` of the given /// Return an iterator over the `local` and `remotes` of the given
/// [`Objects`]. /// [`Objects`].
pub fn iter(&self) -> impl Iterator<Item = &Reference> { pub fn iter(&self) -> impl Iterator<Item = &Reference> {
self.local.iter().chain(self.remotes.iter()) self.0.iter()
}
}
impl From<Vec<Reference>> for Objects {
fn from(refs: Vec<Reference>) -> Self {
Objects(refs)
} }
} }
@ -61,18 +68,13 @@ pub trait Storage {
/// particular object /// particular object
fn objects( fn objects(
&self, &self,
identifier: &Self::Identifier,
typename: &TypeName, typename: &TypeName,
object_id: &ObjectId, object_id: &ObjectId,
) -> Result<Objects, Self::ObjectsError>; ) -> Result<Objects, Self::ObjectsError>;
/// Get all references to objects of a given type within a particular /// Get all references to objects of a given type within a particular
/// identity /// identity
fn types( fn types(&self, typename: &TypeName) -> Result<HashMap<ObjectId, Objects>, Self::TypesError>;
&self,
identifier: &Self::Identifier,
typename: &TypeName,
) -> Result<HashMap<ObjectId, Objects>, Self::TypesError>;
/// Update a ref to a particular collaborative object /// Update a ref to a particular collaborative object
fn update( fn update(

View File

@ -107,26 +107,10 @@ impl object::Storage for Storage {
fn objects( fn objects(
&self, &self,
identifier: &Self::Identifier,
typename: &crate::TypeName, typename: &crate::TypeName,
object_id: &ObjectId, object_id: &ObjectId,
) -> Result<object::Objects, Self::ObjectsError> { ) -> Result<object::Objects, Self::ObjectsError> {
let name = format!( let glob = format!("refs/rad/*/cobs/{}/{}", typename, object_id);
"refs/rad/{}/cobs/{}/{}",
identifier.to_path(),
typename,
object_id
);
let glob = format!(
"refs/rad/{}/*/cobs/{}/{}",
identifier.name.as_str(),
typename,
object_id
);
let local = {
let r = self.raw.find_reference(&name)?;
Some(Reference::try_from(r)?)
};
let remotes = self let remotes = self
.raw .raw
.references_glob(&glob)? .references_glob(&glob)?
@ -135,31 +119,28 @@ impl object::Storage for Storage {
.and_then(|r| Reference::try_from(r).map_err(error::Objects::from)) .and_then(|r| Reference::try_from(r).map_err(error::Objects::from))
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
Ok(object::Objects { local, remotes }) Ok(remotes.into())
} }
fn types( fn types(
&self, &self,
identifier: &Self::Identifier,
typename: &crate::TypeName, typename: &crate::TypeName,
) -> Result<HashMap<ObjectId, object::Objects>, Self::TypesError> { ) -> Result<HashMap<ObjectId, object::Objects>, Self::TypesError> {
let mut objects = HashMap::new(); let mut objects = HashMap::new();
let prefix = format!("refs/rad/{}/cobs/{}", identifier.to_path(), typename); for r in self.raw.references_glob("refs/rad/*")? {
for r in self.raw.references()? {
let r = r?; let r = r?;
let name = r.name().unwrap(); let name = r.name().unwrap();
println!("NAME: {}", name);
let oid = r let oid = r
.target() .target()
.map(ObjectId::from) .map(ObjectId::from)
.expect("BUG: the cob references should be direct"); .expect("BUG: the cob references should be direct");
if name.starts_with(&prefix) { if name.contains(typename.as_str()) {
objects.insert( let reference = Reference::try_from(r)?;
oid, objects
object::Objects { .entry(oid)
local: Some(Reference::try_from(r)?), .and_modify(|objs: &mut object::Objects| objs.push(reference.clone()))
remotes: Vec::new(), .or_insert_with(|| object::Objects::new(reference));
},
);
} }
} }
Ok(objects) Ok(objects)

View File

@ -34,7 +34,7 @@ fn roundtrip() {
) )
.unwrap(); .unwrap();
let expected = get(&storage, &proj.identifier(), &typename, cob.id()) let expected = get(&storage, &typename, cob.id())
.unwrap() .unwrap()
.expect("BUG: cob was missing"); .expect("BUG: cob was missing");
@ -80,7 +80,7 @@ fn list_cobs() {
) )
.unwrap(); .unwrap();
let mut expected = list(&storage, &proj.identifier(), &typename).unwrap(); let mut expected = list(&storage, &typename).unwrap();
expected.sort_by(|x, y| x.id().cmp(y.id())); expected.sort_by(|x, y| x.id().cmp(y.id()));
let mut actual = vec![issue_1, issue_2]; let mut actual = vec![issue_1, issue_2];
@ -115,7 +115,7 @@ fn update_cob() {
) )
.unwrap(); .unwrap();
let not_expected = get(&storage, &proj.identifier(), &typename, cob.id()) let not_expected = get(&storage, &typename, cob.id())
.unwrap() .unwrap()
.expect("BUG: cob was missing"); .expect("BUG: cob was missing");
@ -134,7 +134,7 @@ fn update_cob() {
) )
.unwrap(); .unwrap();
let expected = get(&storage, &proj.identifier(), &typename, updated.id()) let expected = get(&storage, &typename, updated.id())
.unwrap() .unwrap()
.expect("BUG: cob was missing"); .expect("BUG: cob was missing");

View File

@ -21,6 +21,12 @@ use thiserror::Error;
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct TypeName(String); pub struct TypeName(String);
impl TypeName {
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for TypeName { impl fmt::Display for TypeName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.0.as_str()) f.write_str(self.0.as_str())