diff --git a/radicle-cob/src/backend/git/change.rs b/radicle-cob/src/backend/git/change.rs index b9b476e8..9d5aa316 100644 --- a/radicle-cob/src/backend/git/change.rs +++ b/radicle-cob/src/backend/git/change.rs @@ -13,7 +13,7 @@ use crate::{ change::{self, store, Change}, history::entry, signatures::{Signature, Signatures}, - trailers, HistoryType, + trailers, }; const MANIFEST_BLOB_NAME: &str = "manifest"; @@ -154,7 +154,7 @@ impl change::Storage for git2::Repository { let tree = self.find_tree(commit.tree())?; let manifest = load_manifest(self, &tree)?; - let contents = load_contents(self, &tree, &manifest)?; + let contents = load_contents(self, &tree)?; Ok(Change { id, @@ -210,20 +210,15 @@ fn load_manifest( fn load_contents( repo: &git2::Repository, tree: &git2::Tree, - manifest: &store::Manifest, ) -> Result { - Ok(match manifest.history_type { - HistoryType::Radicle | HistoryType::Automerge => { - let contents_tree_entry = tree - .get_name(CHANGE_BLOB_NAME) - .ok_or_else(|| error::Load::NoChange(tree.id().into()))?; - let contents_object = contents_tree_entry.to_object(repo)?; - let contents_blob = contents_object - .as_blob() - .ok_or_else(|| error::Load::ChangeNotBlob(tree.id().into()))?; - contents_blob.content().to_owned() - } - }) + let contents_tree_entry = tree + .get_name(CHANGE_BLOB_NAME) + .ok_or_else(|| error::Load::NoChange(tree.id().into()))?; + let contents_object = contents_tree_entry.to_object(repo)?; + let contents_blob = contents_object + .as_blob() + .ok_or_else(|| error::Load::ChangeNotBlob(tree.id().into()))?; + Ok(contents_blob.content().to_owned()) } fn write_commit( diff --git a/radicle-cob/src/change/store.rs b/radicle-cob/src/change/store.rs index 1269c376..2df8cd71 100644 --- a/radicle-cob/src/change/store.rs +++ b/radicle-cob/src/change/store.rs @@ -7,10 +7,7 @@ use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; -use crate::{ - history::{Contents, HistoryType}, - signatures, TypeName, -}; +use crate::{history::Contents, signatures, TypeName}; pub trait Storage { type CreateError: Error + Send + Sync + 'static; @@ -47,7 +44,7 @@ pub trait Storage { pub struct Create { pub typename: TypeName, - pub history_type: HistoryType, + pub history_type: String, pub tips: Vec, pub message: String, pub contents: Contents, @@ -126,10 +123,10 @@ where } } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Manifest { /// The name given to the type of collaborative object. pub typename: TypeName, /// The type of history for the collaborative oject. - pub history_type: HistoryType, + pub history_type: String, } diff --git a/radicle-cob/src/change_graph.rs b/radicle-cob/src/change_graph.rs index f21f8482..67b10341 100644 --- a/radicle-cob/src/change_graph.rs +++ b/radicle-cob/src/change_graph.rs @@ -102,9 +102,9 @@ impl ChangeGraph { // This is okay because we check that the graph has a root node in // GraphBuilder::build let root = roots.first().unwrap(); - let typename = { + let manifest = { let first_node = &self.graph[*root]; - first_node.typename().clone() + first_node.manifest.clone() }; let topo = Topo::new(&self.graph); let items = topo.iter(&self.graph).map(|idx| { @@ -121,7 +121,7 @@ impl ChangeGraph { evaluate(*root_change.id(), &self.graph, items) }; CollaborativeObject { - typename, + manifest, history, id: self.object_id, } diff --git a/radicle-cob/src/history.rs b/radicle-cob/src/history.rs index 09bb5d83..e8f4eb25 100644 --- a/radicle-cob/src/history.rs +++ b/radicle-cob/src/history.rs @@ -17,16 +17,6 @@ use crate::pruning_fold; pub mod entry; pub use entry::{Clock, Contents, Entry, EntryId, EntryWithClock}; -#[derive( - Clone, Copy, Debug, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, -)] -#[serde(rename_all = "lowercase")] -pub enum HistoryType { - #[default] - Radicle, - Automerge, -} - /// The DAG of changes making up the history of a collaborative object. #[derive(Clone, Debug)] pub struct History { diff --git a/radicle-cob/src/lib.rs b/radicle-cob/src/lib.rs index f4cce633..b2d29c6d 100644 --- a/radicle-cob/src/lib.rs +++ b/radicle-cob/src/lib.rs @@ -92,7 +92,7 @@ pub use change::Change; pub mod identity; pub mod history; -pub use history::{Contents, Entry, History, HistoryType}; +pub use history::{Contents, Entry, History}; mod pruning_fold; diff --git a/radicle-cob/src/object/collaboration.rs b/radicle-cob/src/object/collaboration.rs index 430734ec..a54a5503 100644 --- a/radicle-cob/src/object/collaboration.rs +++ b/radicle-cob/src/object/collaboration.rs @@ -7,6 +7,7 @@ use std::collections::BTreeSet; use git_ext::Oid; +use crate::change::store::Manifest; use crate::{change, identity::Identity, Contents, History, ObjectId, TypeName}; pub mod error; @@ -28,8 +29,8 @@ pub use update::{update, Update}; /// A collaborative object #[derive(Debug, Clone, PartialEq, Eq)] pub struct CollaborativeObject { - /// The typename of this object - pub(crate) typename: TypeName, + /// The manifest of this object + pub(crate) manifest: Manifest, /// The CRDT history we know about for this object pub(crate) history: History, /// The id of the object @@ -46,7 +47,11 @@ impl CollaborativeObject { } pub fn typename(&self) -> &TypeName { - &self.typename + &self.manifest.typename + } + + pub fn manifest(&self) -> &Manifest { + &self.manifest } fn tips(&self) -> BTreeSet { diff --git a/radicle-cob/src/object/collaboration/create.rs b/radicle-cob/src/object/collaboration/create.rs index 052fb4a4..620babc3 100644 --- a/radicle-cob/src/object/collaboration/create.rs +++ b/radicle-cob/src/object/collaboration/create.rs @@ -3,7 +3,7 @@ // This file is part of radicle-link, distributed under the GPLv3 with Radicle // Linking Exception. For full terms see the included LICENSE file. -use crate::{HistoryType, Store}; +use crate::Store; use super::*; @@ -12,7 +12,7 @@ pub struct Create { /// The identity of the author for this object's first change. pub author: Option, /// The type of history that will be used for this object. - pub history_type: HistoryType, + pub history_type: String, /// The CRDT history to initialize this object with. pub contents: Contents, /// The typename for this object. @@ -25,7 +25,7 @@ impl Create { fn create_spec(&self) -> change::Create { change::Create { typename: self.typename.clone(), - history_type: self.history_type, + history_type: self.history_type.clone(), tips: Vec::new(), message: self.message.clone(), contents: self.contents.clone(), @@ -101,7 +101,10 @@ where .map_err(|err| error::Create::Refs { err: Box::new(err) })?; Ok(CollaborativeObject { - typename: args.typename, + manifest: Manifest { + typename: args.typename, + history_type: args.history_type, + }, history, id: init_change.id().into(), }) diff --git a/radicle-cob/src/object/collaboration/update.rs b/radicle-cob/src/object/collaboration/update.rs index a8da328b..3a947865 100644 --- a/radicle-cob/src/object/collaboration/update.rs +++ b/radicle-cob/src/object/collaboration/update.rs @@ -4,8 +4,8 @@ // Linking Exception. For full terms see the included LICENSE file. use crate::{ - change, change_graph::ChangeGraph, identity::Identity, CollaborativeObject, Contents, - HistoryType, ObjectId, Store, TypeName, + change, change_graph::ChangeGraph, identity::Identity, CollaborativeObject, Contents, ObjectId, + Store, TypeName, }; use super::error; @@ -15,7 +15,7 @@ pub struct Update { /// The identity of the author for the update of this object. pub author: Option, /// The type of history that will be used for this object. - pub history_type: HistoryType, + pub history_type: String, /// The CRDT changes to add to the object. pub changes: Contents, /// The object ID of the object to be updated. diff --git a/radicle-cob/src/tests.rs b/radicle-cob/src/tests.rs index b3b78fdb..1730ad28 100644 --- a/radicle-cob/src/tests.rs +++ b/radicle-cob/src/tests.rs @@ -6,8 +6,7 @@ use quickcheck::Arbitrary; use radicle_crypto::Signer; use crate::{ - create, get, list, object, test::arbitrary::Invalid, update, Create, HistoryType, ObjectId, - TypeName, Update, + create, get, list, object, test::arbitrary::Invalid, update, Create, ObjectId, TypeName, Update, }; use super::test; @@ -30,7 +29,7 @@ fn roundtrip() { &proj.identifier(), Create { author: Some(terry), - history_type: HistoryType::Automerge, + history_type: "test".to_string(), contents: Vec::new(), typename: typename.clone(), message: "creating xyz.rad.issue".to_string(), @@ -63,7 +62,7 @@ fn list_cobs() { &proj.identifier(), Create { author: Some(terry.clone()), - history_type: HistoryType::Automerge, + history_type: "test".to_string(), contents: b"issue 1".to_vec(), typename: typename.clone(), message: "creating xyz.rad.issue".to_string(), @@ -78,7 +77,7 @@ fn list_cobs() { &proj.identifier(), Create { author: Some(terry), - history_type: HistoryType::Automerge, + history_type: "test".to_string(), contents: b"issue 2".to_vec(), typename: typename.clone(), message: "commenting xyz.rad.issue".to_string(), @@ -113,7 +112,7 @@ fn update_cob() { &proj.identifier(), Create { author: Some(terry.clone()), - history_type: HistoryType::Automerge, + history_type: "test".to_string(), contents: Vec::new(), typename: typename.clone(), message: "creating xyz.rad.issue".to_string(), @@ -133,7 +132,7 @@ fn update_cob() { Update { author: Some(terry), changes: b"issue 1".to_vec(), - history_type: HistoryType::Automerge, + history_type: "test".to_string(), object_id: *cob.id(), typename: typename.clone(), message: "commenting xyz.rad.issue".to_string(), @@ -174,7 +173,7 @@ fn traverse_cobs() { Create { author: Some(terry), contents: b"issue 1".to_vec(), - history_type: HistoryType::Automerge, + history_type: "test".to_string(), typename: typename.clone(), message: "creating xyz.rad.issue".to_string(), }, @@ -197,7 +196,7 @@ fn traverse_cobs() { Update { author: Some(neil), changes: b"issue 2".to_vec(), - history_type: HistoryType::Automerge, + history_type: "test".to_string(), object_id: *cob.id(), typename, message: "commenting on xyz.rad.issue".to_string(), diff --git a/radicle/src/cob.rs b/radicle/src/cob.rs index 6a2f71c7..7c86d675 100644 --- a/radicle/src/cob.rs +++ b/radicle/src/cob.rs @@ -6,7 +6,7 @@ pub mod thread; pub use cob::{ identity, object::collaboration::error, CollaborativeObject, Contents, Create, Entry, History, - HistoryType, ObjectId, TypeName, Update, + ObjectId, TypeName, Update, }; pub use common::*; diff --git a/radicle/src/cob/store.rs b/radicle/src/cob/store.rs index e6422c78..e41a721a 100644 --- a/radicle/src/cob/store.rs +++ b/radicle/src/cob/store.rs @@ -8,13 +8,16 @@ use serde::Serialize; use crate::cob; use crate::cob::common::Author; use crate::cob::CollaborativeObject; -use crate::cob::{Create, History, HistoryType, ObjectId, TypeName, Update}; +use crate::cob::{Create, History, ObjectId, TypeName, Update}; use crate::crypto::PublicKey; use crate::git; use crate::identity::project; use crate::prelude::*; use crate::storage::git as storage; +/// History type for standard radicle COBs. +pub const HISTORY_TYPE: &str = "radicle"; + /// A type that can be materialized from an event history. /// All collaborative objects implement this trait. pub trait FromHistory: Sized { @@ -102,7 +105,7 @@ where Update { author: Some(cob::Author::from(*signer.public_key())), object_id, - history_type: HistoryType::default(), + history_type: HISTORY_TYPE.to_owned(), typename: T::type_name().clone(), message: message.to_owned(), changes, @@ -125,7 +128,7 @@ where &self.project, Create { author: Some(cob::Author::from(*signer.public_key())), - history_type: HistoryType::default(), + history_type: HISTORY_TYPE.to_owned(), typename: T::type_name().clone(), message: message.to_owned(), contents, @@ -141,6 +144,9 @@ where let cob = cob::get(self.raw, T::type_name(), id)?; if let Some(cob) = cob { + if cob.manifest().history_type != HISTORY_TYPE { + panic!(); + } let (obj, clock) = T::from_history(cob.history())?; Ok(Some((obj, clock))) } else {