cob: Change history type to a string

Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
Alexis Sellier 2022-11-30 11:48:21 +01:00
parent 0dc34dc15d
commit 5a47023ac0
No known key found for this signature in database
11 changed files with 54 additions and 59 deletions

View File

@ -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<entry::Contents, error::Load> {
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<O>(

View File

@ -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<Id> {
pub typename: TypeName,
pub history_type: HistoryType,
pub history_type: String,
pub tips: Vec<Id>,
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,
}

View File

@ -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,
}

View File

@ -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 {

View File

@ -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;

View File

@ -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<Oid> {

View File

@ -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<Author> {
/// The identity of the author for this object's first change.
pub author: Option<Author>,
/// 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<Author> Create<Author> {
fn create_spec(&self) -> change::Create<git_ext::Oid> {
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(),
})

View File

@ -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<Author> {
/// The identity of the author for the update of this object.
pub author: Option<Author>,
/// 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.

View File

@ -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(),

View File

@ -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::*;

View File

@ -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 {