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
/// [`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
/// `object_id` is the identifier for the particular object under that
/// type.
pub fn get<S>(
storage: &S,
identifier: &S::Identifier,
typename: &TypeName,
oid: &ObjectId,
) -> Result<Option<CollaborativeObject>, error::Retrieve>
@ -29,7 +25,7 @@ where
S: Store,
{
let tip_refs = storage
.objects(identifier, typename, oid)
.objects(typename, oid)
.map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?;
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
/// [`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`
/// is the identifier for the particular object under that type.
pub fn changegraph<S>(
storage: &S,
identifier: &S::Identifier,
typename: &TypeName,
oid: &ObjectId,
) -> Result<Option<ChangeGraphInfo>, error::Retrieve>
@ -53,7 +49,7 @@ where
S: Store,
{
let tip_refs = storage
.objects(identifier, typename, oid)
.objects(typename, oid)
.map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?;
Ok(
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
/// [`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.
pub fn list<S>(
storage: &S,
identifier: &S::Identifier,
typename: &TypeName,
) -> Result<Vec<CollaborativeObject>, error::Retrieve>
where
S: Store,
{
let references = storage
.types(identifier, typename)
.types(typename)
.map_err(|err| error::Retrieve::Refs { err: Box::new(err) })?;
log::trace!("loaded {} references", references.len());
let mut result = Vec::new();

View File

@ -76,7 +76,7 @@ where
};
let existing_refs = storage
.objects(identifier, typename, &object_id)
.objects(typename, &object_id)
.map_err(|err| error::Update::Refs { err: Box::new(err) })?;
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
/// [`crate::CollaborativeObject`].
#[derive(Clone, Debug)]
pub struct Objects {
/// 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>,
}
pub struct Objects(Vec<Reference>);
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
/// [`Objects`].
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
fn objects(
&self,
identifier: &Self::Identifier,
typename: &TypeName,
object_id: &ObjectId,
) -> Result<Objects, Self::ObjectsError>;
/// Get all references to objects of a given type within a particular
/// identity
fn types(
&self,
identifier: &Self::Identifier,
typename: &TypeName,
) -> Result<HashMap<ObjectId, Objects>, Self::TypesError>;
fn types(&self, typename: &TypeName) -> Result<HashMap<ObjectId, Objects>, Self::TypesError>;
/// Update a ref to a particular collaborative object
fn update(

View File

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

View File

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

View File

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