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:
parent
d6416c9be1
commit
0bd213d15a
|
|
@ -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()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue