Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
Tidy up COBs code a little
Alexis Sellier committed 3 years ago
commit 49cd26c0b3d7cd71f6dda79d0626bfbf00626dc6
parent bf22cea01471f0e95fd7ecbb6288fb7c4e3f7d8f
10 files changed +186 -169
modified radicle-cob/src/backend/git/change.rs
@@ -80,23 +80,23 @@ pub mod error {
}

impl change::Storage for git2::Repository {
-
    type CreateError = error::Create;
+
    type StoreError = error::Create;
    type LoadError = error::Load;

    type ObjectId = Oid;
    type Resource = Oid;
    type Signatures = Signature;

-
    fn create<Signer>(
+
    fn store<Signer>(
        &self,
        resource: Self::Resource,
        signer: &Signer,
-
        spec: store::Create<Self::ObjectId>,
-
    ) -> Result<Change, Self::CreateError>
+
        spec: store::Template<Self::ObjectId>,
+
    ) -> Result<Change, Self::StoreError>
    where
        Signer: crypto::Signer,
    {
-
        let change::Create {
+
        let change::Template {
            typename,
            history_type,
            tips,
deleted radicle-cob/src/backend/git/objects.rs
modified radicle-cob/src/change.rs
@@ -6,7 +6,7 @@
use git_ext::Oid;

pub mod store;
-
pub use store::{Create, Storage};
+
pub use store::{Storage, Template};

use crate::signatures::Signature;

modified radicle-cob/src/change/store.rs
@@ -12,24 +12,27 @@ use crate::{
    signatures, TypeName,
};

+
/// Change storage.
pub trait Storage {
-
    type CreateError: Error + Send + Sync + 'static;
+
    type StoreError: Error + Send + Sync + 'static;
    type LoadError: Error + Send + Sync + 'static;

    type ObjectId;
    type Resource;
    type Signatures;

+
    /// Store a new change.
    #[allow(clippy::type_complexity)]
-
    fn create<Signer>(
+
    fn store<G>(
        &self,
        authority: Self::Resource,
-
        signer: &Signer,
-
        spec: Create<Self::ObjectId>,
-
    ) -> Result<Change<Self::Resource, Self::ObjectId, Self::Signatures>, Self::CreateError>
+
        signer: &G,
+
        template: Template<Self::ObjectId>,
+
    ) -> Result<Change<Self::Resource, Self::ObjectId, Self::Signatures>, Self::StoreError>
    where
-
        Signer: crypto::Signer;
+
        G: crypto::Signer;

+
    /// Load a change.
    #[allow(clippy::type_complexity)]
    fn load(
        &self,
@@ -37,7 +40,8 @@ pub trait Storage {
    ) -> Result<Change<Self::Resource, Self::ObjectId, Self::Signatures>, Self::LoadError>;
}

-
pub struct Create<Id> {
+
/// Change template, used to create a new change.
+
pub struct Template<Id> {
    pub typename: TypeName,
    pub history_type: String,
    pub tips: Vec<Id>,
modified radicle-cob/src/lib.rs
@@ -131,7 +131,7 @@ pub trait Store
where
    Self: object::Storage
        + change::Storage<
-
            CreateError = git::change::error::Create,
+
            StoreError = git::change::error::Create,
            LoadError = git::change::error::Load,
            ObjectId = git_ext::Oid,
            Resource = git_ext::Oid,
modified radicle-cob/src/object/collaboration/create.rs
@@ -20,8 +20,8 @@ pub struct Create {
}

impl Create {
-
    fn create_spec(&self) -> change::Create<git_ext::Oid> {
-
        change::Create {
+
    fn template(&self) -> change::Template<git_ext::Oid> {
+
        change::Template {
            typename: self.typename.clone(),
            history_type: self.history_type.clone(),
            tips: Vec::new(),
@@ -68,7 +68,7 @@ where
    } = &args;

    let init_change = storage
-
        .create(resource.content_id(), signer, args.create_spec())
+
        .store(resource.content_id(), signer, args.template())
        .map_err(error::Create::from)?;

    let history = History::new_from_root(
modified radicle-cob/src/object/collaboration/update.rs
@@ -70,10 +70,10 @@ where
        .map(|graph| graph.evaluate())
        .ok_or(error::Update::NoSuchObject)?;

-
    let change = storage.create(
+
    let change = storage.store(
        resource.content_id(),
        signer,
-
        change::Create {
+
        change::Template {
            tips: object.tips().iter().cloned().collect(),
            history_type,
            contents: changes.clone(),
modified radicle-cob/src/test/storage.rs
@@ -59,26 +59,26 @@ impl Storage {
impl Store for Storage {}

impl change::Storage for Storage {
-
    type CreateError = <git2::Repository as change::Storage>::CreateError;
+
    type StoreError = <git2::Repository as change::Storage>::StoreError;
    type LoadError = <git2::Repository as change::Storage>::LoadError;

    type ObjectId = <git2::Repository as change::Storage>::ObjectId;
    type Resource = <git2::Repository as change::Storage>::Resource;
    type Signatures = <git2::Repository as change::Storage>::Signatures;

-
    fn create<Signer>(
+
    fn store<Signer>(
        &self,
        authority: Self::Resource,
        signer: &Signer,
-
        spec: change::Create<Self::ObjectId>,
+
        spec: change::Template<Self::ObjectId>,
    ) -> Result<
        change::store::Change<Self::Resource, Self::ObjectId, Self::Signatures>,
-
        Self::CreateError,
+
        Self::StoreError,
    >
    where
        Signer: crypto::Signer,
    {
-
        self.as_raw().create(authority, signer, spec)
+
        self.as_raw().store(authority, signer, spec)
    }

    fn load(
modified radicle/src/storage/git.rs
@@ -1,3 +1,4 @@
+
pub mod cob;
pub mod transport;

use std::collections::{BTreeMap, HashMap};
@@ -7,7 +8,6 @@ use std::{fs, io};
use crypto::{Signer, Unverified, Verified};
use git_ref_format::refspec;
use once_cell::sync::Lazy;
-
use radicle_cob::{self as cob, change};

use crate::git;
use crate::identity;
@@ -61,28 +61,6 @@ impl ProjectError {
    }
}

-
#[derive(Error, Debug)]
-
pub enum CobObjectsError {
-
    #[error(transparent)]
-
    Convert(#[from] cob::object::storage::convert::Error),
-
    #[error(transparent)]
-
    Git(#[from] git2::Error),
-
}
-

-
#[derive(Error, Debug)]
-
pub enum CobTypesError {
-
    #[error(transparent)]
-
    Convert(#[from] cob::object::storage::convert::Error),
-
    #[error(transparent)]
-
    Git(#[from] git2::Error),
-
    #[error(transparent)]
-
    ParseKey(#[from] crypto::Error),
-
    #[error(transparent)]
-
    ParseObjectId(#[from] cob::object::ParseObjectId),
-
    #[error(transparent)]
-
    RefFormat(#[from] git_ref_format::Error),
-
}
-

#[derive(Debug, Clone)]
pub struct Storage {
    path: PathBuf,
@@ -699,128 +677,6 @@ impl WriteRepository for Repository {
    }
}

-
impl cob::Store for Repository {}
-

-
impl change::Storage for Repository {
-
    type CreateError = <git2::Repository as change::Storage>::CreateError;
-
    type LoadError = <git2::Repository as change::Storage>::LoadError;
-

-
    type ObjectId = <git2::Repository as change::Storage>::ObjectId;
-
    type Resource = <git2::Repository as change::Storage>::Resource;
-
    type Signatures = <git2::Repository as change::Storage>::Signatures;
-

-
    fn create<Signer>(
-
        &self,
-
        authority: Self::Resource,
-
        signer: &Signer,
-
        spec: change::Create<Self::ObjectId>,
-
    ) -> Result<cob::Change, Self::CreateError>
-
    where
-
        Signer: crypto::Signer,
-
    {
-
        self.backend.create(authority, signer, spec)
-
    }
-

-
    fn load(&self, id: Self::ObjectId) -> Result<cob::Change, Self::LoadError> {
-
        self.backend.load(id)
-
    }
-
}
-

-
impl cob::object::Storage for Repository {
-
    type ObjectsError = CobObjectsError;
-
    type TypesError = CobTypesError;
-
    type UpdateError = git2::Error;
-
    type RemoveError = git2::Error;
-

-
    type Identifier = RemoteId;
-

-
    fn objects(
-
        &self,
-
        typename: &cob::TypeName,
-
        object_id: &cob::ObjectId,
-
    ) -> Result<cob::object::Objects, Self::ObjectsError> {
-
        let refs = self
-
            .backend
-
            .references_glob(git::refs::storage::cobs(typename, object_id).as_str())?;
-
        let refs = refs
-
            .map(|r| {
-
                r.map_err(Self::ObjectsError::from).and_then(|r| {
-
                    cob::object::Reference::try_from(r).map_err(Self::ObjectsError::from)
-
                })
-
            })
-
            .collect::<Result<Vec<_>, _>>()?;
-
        Ok(refs.into())
-
    }
-

-
    fn types(
-
        &self,
-
        typename: &cob::TypeName,
-
    ) -> Result<HashMap<cob::ObjectId, cob::object::Objects>, Self::TypesError> {
-
        let mut references = self.backend.references()?.filter_map(|reference| {
-
            let reference = reference.ok()?;
-
            match RefStr::try_from_str(reference.name()?) {
-
                Ok(name) => {
-
                    let (ty, object_id) = cob::object::parse_refstr(&name)?;
-
                    if ty == *typename {
-
                        Some(
-
                            cob::object::Reference::try_from(reference)
-
                                .map_err(Self::TypesError::from)
-
                                .map(|reference| (object_id, reference)),
-
                        )
-
                    } else {
-
                        None
-
                    }
-
                }
-
                Err(err) => Some(Err(err.into())),
-
            }
-
        });
-

-
        references.try_fold(HashMap::new(), |mut objects, result| {
-
            let (oid, reference) = result?;
-
            objects
-
                .entry(oid)
-
                .and_modify(|objs: &mut cob::object::Objects| objs.push(reference.clone()))
-
                .or_insert_with(|| cob::object::Objects::new(reference));
-
            Ok(objects)
-
        })
-
    }
-

-
    fn update(
-
        &self,
-
        identifier: &Self::Identifier,
-
        typename: &cob::TypeName,
-
        object_id: &cob::ObjectId,
-
        change: &cob::Change,
-
    ) -> Result<(), Self::UpdateError> {
-
        self.backend.reference(
-
            git::refs::storage::cob(identifier, typename, object_id).as_str(),
-
            (*change.id()).into(),
-
            true,
-
            &format!(
-
                "Updating collaborative object '{}/{}' with new change {}",
-
                typename,
-
                object_id,
-
                change.id()
-
            ),
-
        )?;
-

-
        Ok(())
-
    }
-

-
    fn remove(
-
        &self,
-
        identifier: &Self::Identifier,
-
        typename: &cob::TypeName,
-
        object_id: &cob::ObjectId,
-
    ) -> Result<(), Self::RemoveError> {
-
        let mut reference = self
-
            .backend
-
            .find_reference(git::refs::storage::cob(identifier, typename, object_id).as_str())?;
-

-
        reference.delete().map_err(Self::RemoveError::from)
-
    }
-
}
-

pub mod trailers {
    use std::str::FromStr;

added radicle/src/storage/git/cob.rs
@@ -0,0 +1,157 @@
+
//! COB storage Git backend.
+
use std::collections::HashMap;
+

+
use radicle_cob as cob;
+
use radicle_cob::change;
+

+
use crate::git;
+
use crate::storage::Error;
+

+
pub use crate::git::*;
+
pub use cob::*;
+

+
use super::{RemoteId, Repository};
+

+
#[derive(Error, Debug)]
+
pub enum ObjectsError {
+
    #[error(transparent)]
+
    Convert(#[from] cob::object::storage::convert::Error),
+
    #[error(transparent)]
+
    Git(#[from] git2::Error),
+
}
+

+
#[derive(Error, Debug)]
+
pub enum TypesError {
+
    #[error(transparent)]
+
    Convert(#[from] cob::object::storage::convert::Error),
+
    #[error(transparent)]
+
    Git(#[from] git2::Error),
+
    #[error(transparent)]
+
    ParseKey(#[from] crypto::Error),
+
    #[error(transparent)]
+
    ParseObjectId(#[from] cob::object::ParseObjectId),
+
    #[error(transparent)]
+
    RefFormat(#[from] git_ref_format::Error),
+
}
+

+
impl cob::Store for Repository {}
+

+
impl change::Storage for Repository {
+
    type StoreError = <git2::Repository as change::Storage>::StoreError;
+
    type LoadError = <git2::Repository as change::Storage>::LoadError;
+

+
    type ObjectId = <git2::Repository as change::Storage>::ObjectId;
+
    type Resource = <git2::Repository as change::Storage>::Resource;
+
    type Signatures = <git2::Repository as change::Storage>::Signatures;
+

+
    fn store<Signer>(
+
        &self,
+
        authority: Self::Resource,
+
        signer: &Signer,
+
        spec: change::Template<Self::ObjectId>,
+
    ) -> Result<cob::Change, Self::StoreError>
+
    where
+
        Signer: crypto::Signer,
+
    {
+
        self.backend.store(authority, signer, spec)
+
    }
+

+
    fn load(&self, id: Self::ObjectId) -> Result<cob::Change, Self::LoadError> {
+
        self.backend.load(id)
+
    }
+
}
+

+
impl cob::object::Storage for Repository {
+
    type ObjectsError = ObjectsError;
+
    type TypesError = TypesError;
+
    type UpdateError = git2::Error;
+
    type RemoveError = git2::Error;
+

+
    type Identifier = RemoteId;
+

+
    fn objects(
+
        &self,
+
        typename: &cob::TypeName,
+
        object_id: &cob::ObjectId,
+
    ) -> Result<cob::object::Objects, Self::ObjectsError> {
+
        let refs = self
+
            .backend
+
            .references_glob(git::refs::storage::cobs(typename, object_id).as_str())?;
+
        let refs = refs
+
            .map(|r| {
+
                r.map_err(Self::ObjectsError::from).and_then(|r| {
+
                    cob::object::Reference::try_from(r).map_err(Self::ObjectsError::from)
+
                })
+
            })
+
            .collect::<Result<Vec<_>, _>>()?;
+
        Ok(refs.into())
+
    }
+

+
    fn types(
+
        &self,
+
        typename: &cob::TypeName,
+
    ) -> Result<HashMap<cob::ObjectId, cob::object::Objects>, Self::TypesError> {
+
        let mut references = self.backend.references()?.filter_map(|reference| {
+
            let reference = reference.ok()?;
+
            match RefStr::try_from_str(reference.name()?) {
+
                Ok(name) => {
+
                    let (ty, object_id) = cob::object::parse_refstr(&name)?;
+
                    if ty == *typename {
+
                        Some(
+
                            cob::object::Reference::try_from(reference)
+
                                .map_err(Self::TypesError::from)
+
                                .map(|reference| (object_id, reference)),
+
                        )
+
                    } else {
+
                        None
+
                    }
+
                }
+
                Err(err) => Some(Err(err.into())),
+
            }
+
        });
+

+
        references.try_fold(HashMap::new(), |mut objects, result| {
+
            let (oid, reference) = result?;
+
            objects
+
                .entry(oid)
+
                .and_modify(|objs: &mut cob::object::Objects| objs.push(reference.clone()))
+
                .or_insert_with(|| cob::object::Objects::new(reference));
+
            Ok(objects)
+
        })
+
    }
+

+
    fn update(
+
        &self,
+
        identifier: &Self::Identifier,
+
        typename: &cob::TypeName,
+
        object_id: &cob::ObjectId,
+
        change: &cob::Change,
+
    ) -> Result<(), Self::UpdateError> {
+
        self.backend.reference(
+
            git::refs::storage::cob(identifier, typename, object_id).as_str(),
+
            (*change.id()).into(),
+
            true,
+
            &format!(
+
                "Updating collaborative object '{}/{}' with new change {}",
+
                typename,
+
                object_id,
+
                change.id()
+
            ),
+
        )?;
+

+
        Ok(())
+
    }
+

+
    fn remove(
+
        &self,
+
        identifier: &Self::Identifier,
+
        typename: &cob::TypeName,
+
        object_id: &cob::ObjectId,
+
    ) -> Result<(), Self::RemoveError> {
+
        let mut reference = self
+
            .backend
+
            .find_reference(git::refs::storage::cob(identifier, typename, object_id).as_str())?;
+

+
        reference.delete().map_err(Self::RemoveError::from)
+
    }
+
}