diff --git a/radicle-cli/src/commands/patch/edit.rs b/radicle-cli/src/commands/patch/edit.rs index 075bf36f..a7053062 100644 --- a/radicle-cli/src/commands/patch/edit.rs +++ b/radicle-cli/src/commands/patch/edit.rs @@ -36,7 +36,7 @@ pub fn run( return Ok(()); } - let root = patch.id.into(); + let root = *patch.id; let target = patch.target(); patch.transaction("Edit", &signer, |tx| { diff --git a/radicle-cli/src/commands/patch/list.rs b/radicle-cli/src/commands/patch/list.rs index 94ce3acb..ede4ac07 100644 --- a/radicle-cli/src/commands/patch/list.rs +++ b/radicle-cli/src/commands/patch/list.rs @@ -145,7 +145,7 @@ pub fn timeline( for (revision_id, revision) in patch.revisions() { // Don't show an "update" line for the first revision. - if **revision_id != **patch_id { + if *revision_id != **patch_id { timeline.push(( revision.timestamp(), term::Line::spaced( diff --git a/radicle-cob/src/backend/git/change.rs b/radicle-cob/src/backend/git/change.rs index a6488e0e..f0ecae45 100644 --- a/radicle-cob/src/backend/git/change.rs +++ b/radicle-cob/src/backend/git/change.rs @@ -12,11 +12,10 @@ use once_cell::sync::Lazy; use radicle_git_ext::commit::trailers::OwnedTrailer; use crate::change::store::Version; -use crate::history::entry::Timestamp; use crate::signatures; use crate::{ - change::{self, store, Change}, - history::entry, + change, + change::{store, Contents, Entry, Timestamp}, signatures::{ExtendedSignature, Signatures}, trailers, Embed, }; @@ -99,7 +98,7 @@ impl change::Storage for git2::Repository { parents: Vec, signer: &Signer, spec: store::Template, - ) -> Result + ) -> Result where Signer: crypto::Signer, { @@ -129,7 +128,7 @@ impl change::Storage for git2::Repository { tree, )?; - Ok(Change { + Ok(Entry { id, revision: revision.into(), signature, @@ -149,7 +148,7 @@ impl change::Storage for git2::Repository { .collect::>()) } - fn load(&self, id: Self::ObjectId) -> Result { + fn load(&self, id: Self::ObjectId) -> Result { let commit = Commit::read(self, id.into())?; let timestamp = git2::Time::from(commit.committer().time).seconds() as u64; let resource = parse_resource_trailer(commit.trailers())?; @@ -172,7 +171,7 @@ impl change::Storage for git2::Repository { let manifest = load_manifest(self, &tree)?; let contents = load_contents(self, &tree)?; - Ok(Change { + Ok(Entry { id, revision: tree.id().into(), signature: ExtendedSignature::new(key, sig), @@ -220,10 +219,7 @@ fn load_manifest( }) } -fn load_contents( - repo: &git2::Repository, - tree: &git2::Tree, -) -> Result { +fn load_contents(repo: &git2::Repository, tree: &git2::Tree) -> Result { let ops = tree .iter() .filter_map(|entry| { diff --git a/radicle-cob/src/change.rs b/radicle-cob/src/change.rs index 1a9a0fb6..1ae1b51b 100644 --- a/radicle-cob/src/change.rs +++ b/radicle-cob/src/change.rs @@ -3,11 +3,11 @@ use git_ext::Oid; pub mod store; -pub use store::{Storage, Template}; +pub use store::{Contents, EntryId, Storage, Template, Timestamp}; use crate::signatures::ExtendedSignature; /// A single change in the change graph. The layout of changes in the repository /// is specified in the RFC (docs/rfc/0662-collaborative-objects.adoc) /// under "Change Commits". -pub type Change = store::Change; +pub type Entry = store::Entry; diff --git a/radicle-cob/src/change/store.rs b/radicle-cob/src/change/store.rs index 663898fe..16deac6d 100644 --- a/radicle-cob/src/change/store.rs +++ b/radicle-cob/src/change/store.rs @@ -6,12 +6,9 @@ use nonempty::NonEmpty; use radicle_git_ext::Oid; use serde::{Deserialize, Serialize}; -use crate::{ - history::{Contents, Timestamp}, - signatures, TypeName, -}; +use crate::{signatures, TypeName}; -/// Change storage. +/// Change entry storage. pub trait Storage { type StoreError: Error + Send + Sync + 'static; type LoadError: Error + Send + Sync + 'static; @@ -20,7 +17,7 @@ pub trait Storage { type Parent; type Signatures; - /// Store a new change. + /// Store a new change entry. #[allow(clippy::type_complexity)] fn store( &self, @@ -28,16 +25,16 @@ pub trait Storage { parents: Vec, signer: &G, template: Template, - ) -> Result, Self::StoreError> + ) -> Result, Self::StoreError> where G: crypto::Signer; - /// Load a change. + /// Load a change entry. #[allow(clippy::type_complexity)] fn load( &self, id: Self::ObjectId, - ) -> Result, Self::LoadError>; + ) -> Result, Self::LoadError>; /// Returns the parents of the object with the specified ID. fn parents_of(&self, id: &Oid) -> Result, Self::LoadError>; @@ -52,8 +49,18 @@ pub struct Template { pub contents: NonEmpty>, } +/// Entry contents. +/// This is the change payload. +pub type Contents = NonEmpty>; + +/// Local time in seconds since epoch. +pub type Timestamp = u64; + +/// A unique identifier for a history entry. +pub type EntryId = Oid; + #[derive(Clone, Debug)] -pub struct Change { +pub struct Entry { /// The content address of the `Change` itself. pub id: Id, /// The content address of the tree of the `Change`. @@ -75,7 +82,7 @@ pub struct Change { pub timestamp: Timestamp, } -impl fmt::Display for Change +impl fmt::Display for Entry where Id: fmt::Display, { @@ -84,7 +91,7 @@ where } } -impl Change { +impl Entry { pub fn id(&self) -> &Id { &self.id } @@ -102,7 +109,7 @@ impl Change { } } -impl Change +impl Entry where Id: AsRef<[u8]>, { @@ -113,13 +120,17 @@ where } } -impl Change +impl Entry where Id: AsRef<[u8]>, { pub fn valid_signatures(&self) -> bool { self.signature.verify(self.revision.as_ref()) } + + pub fn author(&self) -> &crypto::PublicKey { + &self.signature.key + } } #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] diff --git a/radicle-cob/src/change_graph.rs b/radicle-cob/src/change_graph.rs index 8bae80ff..9045ebbc 100644 --- a/radicle-cob/src/change_graph.rs +++ b/radicle-cob/src/change_graph.rs @@ -7,14 +7,14 @@ use git_ext::Oid; use radicle_dag::Dag; use crate::{ - change, history::EntryId, object, signatures::ExtendedSignature, Change, CollaborativeObject, - Entry, History, ObjectId, TypeName, + change, history::EntryId, object, signatures::ExtendedSignature, CollaborativeObject, Entry, + History, ObjectId, TypeName, }; /// The graph of changes for a particular collaborative object pub(super) struct ChangeGraph { object_id: ObjectId, - graph: Dag, + graph: Dag, } impl ChangeGraph { @@ -96,20 +96,7 @@ impl ChangeGraph { if !change.valid_signatures() { return ControlFlow::Break(graph); } - let entry = Entry::new( - *change.id(), - change.signature.key, - change.resource, - change.contents().clone(), - change - .parents - .iter() - .cloned() - .map(|oid| oid.into()) - .collect(), - change.timestamp, - change.manifest.clone(), - ); + let entry = change.value.clone(); let id = *entry.id(); graph.node(id, entry); @@ -141,7 +128,7 @@ impl ChangeGraph { } struct GraphBuilder { - graph: Dag, + graph: Dag, } impl Default for GraphBuilder { @@ -157,7 +144,7 @@ impl GraphBuilder { &mut self, storage: &S, commit_id: Oid, - change: Change, + change: Entry, ) -> Result, S::LoadError> where S: change::Storage, diff --git a/radicle-cob/src/history.rs b/radicle-cob/src/history.rs index 82194ecc..fd7ca417 100644 --- a/radicle-cob/src/history.rs +++ b/radicle-cob/src/history.rs @@ -3,13 +3,9 @@ use std::{cmp::Ordering, collections::BTreeSet, ops::ControlFlow}; use git_ext::Oid; -use radicle_crypto::PublicKey; use radicle_dag::Dag; -pub mod entry; -pub use entry::{Contents, Entry, EntryId, Timestamp}; - -use crate::Manifest; +pub use crate::change::{Contents, Entry, EntryId, Timestamp}; /// The DAG of changes making up the history of a collaborative object. #[derive(Clone, Debug)] @@ -36,32 +32,11 @@ impl History { Self { root, graph } } - pub fn new_from_root( - id: Id, - actor: PublicKey, - resource: Oid, - contents: Contents, - timestamp: Timestamp, - manifest: Manifest, - ) -> Self - where - Id: Into, - { - let id = id.into(); - let root = Entry { - id, - actor, - resource, - contents, - parents: vec![], - timestamp, - manifest, - }; + /// Create a new history from a root entry. + pub fn new_from_root(root: Entry) -> Self { + let id = *root.id(); - Self { - root: id, - graph: Dag::root(id, root), - } + Self::new(id, Dag::root(id, root)) } /// Get the current history timestamp. @@ -69,17 +44,14 @@ impl History { pub fn timestamp(&self) -> Timestamp { self.graph .tips() - .map(|(_, n)| n.timestamp()) + .map(|(_, n)| n.timestamp) .max() .unwrap_or_default() } /// Get all the tips of the graph. pub fn tips(&self) -> BTreeSet { - self.graph - .tips() - .map(|(_, entry)| (*entry.id()).into()) - .collect() + self.graph.tips().map(|(_, entry)| *entry.id()).collect() } /// A topological (parents before children) traversal of the dependency @@ -109,34 +81,14 @@ impl History { } /// Extend this history with a new entry. - pub fn extend( - &mut self, - new_id: Id, - new_actor: PublicKey, - new_resource: Oid, - new_contents: Contents, - new_parents: Vec, - new_timestamp: Timestamp, - manifest: Manifest, - ) where - Id: Into, - { + pub fn extend(&mut self, change: Entry) { let tips = self.tips(); - let new_id = new_id.into(); - let new_entry = Entry::new( - new_id, - new_actor, - new_resource, - new_contents, - new_parents, - new_timestamp, - manifest, - ); + let id = *change.id(); - self.graph.node(new_id, new_entry); + self.graph.node(id, change); for tip in tips { - self.graph.dependency(new_id, (*tip).into()); + self.graph.dependency(id, (*tip).into()); } } diff --git a/radicle-cob/src/history/entry.rs b/radicle-cob/src/history/entry.rs deleted file mode 100644 index 4a3a3b2c..00000000 --- a/radicle-cob/src/history/entry.rs +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright © 2021 The Radicle Link Contributors - -use std::fmt; -use std::ops::Deref; -use std::str::FromStr; - -use git_ext::Oid; -use nonempty::NonEmpty; -use radicle_crypto::PublicKey; -use serde::{Deserialize, Serialize}; - -use crate::{object, Manifest, ObjectId, Version}; - -/// Entry contents. -/// This is the change payload. -pub type Contents = NonEmpty>; - -/// Local time in seconds since epoch. -pub type Timestamp = u64; - -/// A unique identifier for a history entry. -#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct EntryId(Oid); - -impl fmt::Display for EntryId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl FromStr for EntryId { - type Err = git_ext::Error; - - fn from_str(s: &str) -> Result { - let oid = git_ext::Oid::try_from(s)?; - - Ok(Self(oid)) - } -} - -impl From for EntryId { - fn from(id: git2::Oid) -> Self { - Self(id.into()) - } -} - -impl From for EntryId { - fn from(id: Oid) -> Self { - Self(id) - } -} - -impl From for Oid { - fn from(EntryId(id): EntryId) -> Self { - id - } -} - -impl From<&EntryId> for object::ObjectId { - fn from(EntryId(id): &EntryId) -> Self { - id.into() - } -} - -impl From for EntryId { - fn from(id: ObjectId) -> Self { - Self(*id) - } -} - -impl Deref for EntryId { - type Target = Oid; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// One entry in the dependency graph for a change -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Entry { - /// The identifier for this entry - pub(super) id: EntryId, - /// The actor that authored this entry. - pub(super) actor: PublicKey, - /// The content-address for the resource this entry lives under. - /// If the resource was updated, this should point to its latest version. - pub(super) resource: Oid, - /// Parent entries. - pub(super) parents: Vec, - /// The contents of this entry. - pub(super) contents: Contents, - /// The entry timestamp, as seconds since epoch. - pub(super) timestamp: Timestamp, - /// COB manifest. - pub(super) manifest: Manifest, -} - -impl Entry { - pub fn new( - id: Id, - actor: PublicKey, - resource: Oid, - contents: Contents, - parents: Vec, - timestamp: Timestamp, - manifest: Manifest, - ) -> Self - where - Id: Into, - { - Self { - id: id.into(), - actor, - resource, - contents, - timestamp, - parents, - manifest, - } - } - - /// The current `Oid` of the resource this change lives under. - pub fn resource(&self) -> Oid { - self.resource - } - - /// Parent entries. - pub fn parents(&self) -> &[EntryId] { - &self.parents - } - - /// The public key of the actor. - pub fn actor(&self) -> &PublicKey { - &self.actor - } - - /// The COB version of this entry. - pub fn version(&self) -> &Version { - &self.manifest.version - } - - /// The COB manifest. - pub fn manifest(&self) -> &Manifest { - &self.manifest - } - - /// The entry timestamp. - pub fn timestamp(&self) -> Timestamp { - self.timestamp - } - - /// The contents of this change - pub fn contents(&self) -> &Contents { - &self.contents - } - - /// Entry ID. - pub fn id(&self) -> &EntryId { - &self.id - } -} diff --git a/radicle-cob/src/lib.rs b/radicle-cob/src/lib.rs index 61d683ac..d7068095 100644 --- a/radicle-cob/src/lib.rs +++ b/radicle-cob/src/lib.rs @@ -6,9 +6,6 @@ //! Collaborative objects are graphs of CRDTs. The current CRDTs that //! is intended to be used are specifically [automerge] CRDTs. //! -//! The initial design is proposed at [RFC-0662], and this -//! implementation keeps to most of its design principle. -//! //! ## Basic Types //! //! The basic types that are found in `radicle-cob` are: @@ -55,15 +52,14 @@ //! automerge document and deserialize into an application defined //! object. //! -//! This traversal is also the point at which the [`Entry::actor`] +//! This traversal is also the point at which the [`Entry::author`] //! and [`Entry::resource`] can be retrieved to apply any kind of -//! filtering logic. For example, a specific `actor`'s change may be +//! filtering logic. For example, a specific `author`'s change may be //! egregious, spouting terrible libel about Radicle. It is at this //! point that the `actor`'s change can be filtered out from the //! final product of the traversal. //! //! [automerge]: https://automerge.org -//! [RFC-0662]: https://github.com/radicle-dev/radicle-link/blob/master/docs/rfc/0662-collaborative-objects.adoc #[cfg(test)] extern crate qcheck; @@ -81,11 +77,11 @@ mod change_graph; mod trailers; pub mod change; -pub use change::store::{Embed, Manifest, Version}; -pub use change::Change; +pub use change::store::{Contents, Embed, Manifest, Version}; +pub use change::Entry; pub mod history; -pub use history::{Contents, Entry, History}; +pub use history::History; pub mod signatures; use signatures::ExtendedSignature; diff --git a/radicle-cob/src/object/collaboration/create.rs b/radicle-cob/src/object/collaboration/create.rs index ac0a6a5d..9e0f5c8e 100644 --- a/radicle-cob/src/object/collaboration/create.rs +++ b/radicle-cob/src/object/collaboration/create.rs @@ -36,7 +36,7 @@ impl Create { /// Create a new [`CollaborativeObject`]. /// /// The `storage` is the backing storage for storing -/// [`crate::Change`]s at content-addressable locations. Please see +/// [`crate::Entry`]s at content-addressable locations. Please see /// [`Store`] for further information. /// /// The `signer` is expected to be a cryptographic signing key. This @@ -74,14 +74,7 @@ where .update(identifier, &type_name, &object_id, &init_change) .map_err(|err| error::Create::Refs { err: Box::new(err) })?; - let history = History::new_from_root( - *init_change.id(), - init_change.signature.key, - resource, - init_change.contents, - init_change.timestamp, - init_change.manifest, - ); + let history = History::new_from_root(init_change); Ok(CollaborativeObject { manifest: Manifest::new(type_name, version), diff --git a/radicle-cob/src/object/collaboration/get.rs b/radicle-cob/src/object/collaboration/get.rs index 32750bb8..2ef1e2c2 100644 --- a/radicle-cob/src/object/collaboration/get.rs +++ b/radicle-cob/src/object/collaboration/get.rs @@ -7,7 +7,7 @@ use super::error; /// Get a [`CollaborativeObject`], if it exists. /// /// The `storage` is the backing storage for storing -/// [`crate::Change`]s at content-addressable locations. Please see +/// [`crate::Entry`]s at content-addressable locations. Please see /// [`Store`] for further information. /// /// The `typename` is the type of object to be found, while the diff --git a/radicle-cob/src/object/collaboration/info.rs b/radicle-cob/src/object/collaboration/info.rs index 2172efa8..5e885c9f 100644 --- a/radicle-cob/src/object/collaboration/info.rs +++ b/radicle-cob/src/object/collaboration/info.rs @@ -27,7 +27,7 @@ pub struct ChangeGraphInfo { /// is mostly useful for debugging and testing /// /// The `storage` is the backing storage for storing -/// [`crate::Change`]s at content-addressable locations. Please see +/// [`crate::Entry`]s at content-addressable locations. Please see /// [`Store`] for further information. /// /// The `typename` is the type of object to be found, while the `oid` diff --git a/radicle-cob/src/object/collaboration/list.rs b/radicle-cob/src/object/collaboration/list.rs index 0acecea3..05bf6625 100644 --- a/radicle-cob/src/object/collaboration/list.rs +++ b/radicle-cob/src/object/collaboration/list.rs @@ -7,7 +7,7 @@ use super::error; /// List a set of [`CollaborativeObject`]. /// /// The `storage` is the backing storage for storing -/// [`crate::Change`]s at content-addressable locations. Please see +/// [`crate::Entry`]s at content-addressable locations. Please see /// [`Store`] for further information. /// /// The `typename` is the type of objects to be listed. diff --git a/radicle-cob/src/object/collaboration/remove.rs b/radicle-cob/src/object/collaboration/remove.rs index 334148a0..13e8d9fd 100644 --- a/radicle-cob/src/object/collaboration/remove.rs +++ b/radicle-cob/src/object/collaboration/remove.rs @@ -7,7 +7,7 @@ use super::error; /// Remove a [`crate::CollaborativeObject`]. /// /// The `storage` is the backing storage for storing -/// [`crate::Change`]s at content-addressable locations. Please see +/// [`crate::Entry`]s at content-addressable locations. Please see /// [`Store`] for further information. /// /// The `typename` is the type of object to be found, while the diff --git a/radicle-cob/src/object/collaboration/update.rs b/radicle-cob/src/object/collaboration/update.rs index 294f004f..a4d98da8 100644 --- a/radicle-cob/src/object/collaboration/update.rs +++ b/radicle-cob/src/object/collaboration/update.rs @@ -38,7 +38,7 @@ pub struct Update { /// Update an existing [`CollaborativeObject`]. /// /// The `storage` is the backing storage for storing -/// [`crate::Change`]s at content-addressable locations. Please see +/// [`crate::Entry`]s at content-addressable locations. Please see /// [`Store`] for further information. /// /// The `signer` is expected to be a cryptographic signing key. This @@ -99,21 +99,14 @@ where .update(identifier, typename, &object_id, &change) .map_err(|err| error::Update::Refs { err: Box::new(err) })?; - let parents: Vec = change.parents.into_iter().map(|oid| oid.into()).collect(); + let parents = change.parents.to_vec(); + let head = change.id; - object.history.extend( - change.id, - change.signature.key, - change.resource, - change.contents, - parents.clone(), - change.timestamp, - change.manifest, - ); + object.history.extend(change); Ok(Updated { object, - head: change.id, + head, parents, }) } diff --git a/radicle-cob/src/object/storage.rs b/radicle-cob/src/object/storage.rs index aeddbce4..5ddb3fad 100644 --- a/radicle-cob/src/object/storage.rs +++ b/radicle-cob/src/object/storage.rs @@ -5,7 +5,7 @@ use std::{collections::BTreeMap, error::Error}; use git_ext::ref_format::RefString; use git_ext::Oid; -use crate::change::Change; +use crate::change::Entry; use crate::{ObjectId, TypeName}; /// The [`Reference`]s that refer to the commits that make up a @@ -78,7 +78,7 @@ pub trait Storage { identifier: &Self::Identifier, typename: &TypeName, object_id: &ObjectId, - change: &Change, + change: &Entry, ) -> Result<(), Self::UpdateError>; /// Remove a ref to a particular collaborative object diff --git a/radicle-cob/src/test/storage.rs b/radicle-cob/src/test/storage.rs index 7c83a2ad..43b4fd8e 100644 --- a/radicle-cob/src/test/storage.rs +++ b/radicle-cob/src/test/storage.rs @@ -73,7 +73,7 @@ impl change::Storage for Storage { signer: &Signer, spec: change::Template, ) -> Result< - change::store::Change, + change::store::Entry, Self::StoreError, > where @@ -85,10 +85,8 @@ impl change::Storage for Storage { fn load( &self, id: Self::ObjectId, - ) -> Result< - change::store::Change, - Self::LoadError, - > { + ) -> Result, Self::LoadError> + { self.as_raw().load(id) } @@ -156,7 +154,7 @@ impl object::Storage for Storage { identifier: &Self::Identifier, typename: &crate::TypeName, object_id: &ObjectId, - change: &change::Change, + change: &change::Entry, ) -> Result<(), Self::UpdateError> { let name = format!( "refs/rad/{}/cobs/{}/{}", diff --git a/radicle-cob/src/tests.rs b/radicle-cob/src/tests.rs index 68506e7b..def62425 100644 --- a/radicle-cob/src/tests.rs +++ b/radicle-cob/src/tests.rs @@ -213,7 +213,7 @@ fn traverse_cobs() { // traverse over the history and filter by changes that were only authorized by terry let contents = object.history().traverse(Vec::new(), |mut acc, _, entry| { - if entry.actor() == terry_signer.public_key() { + if entry.author() == terry_signer.public_key() { acc.push(entry.contents().head.clone()); } ControlFlow::Continue(acc) diff --git a/radicle/src/cob/issue.rs b/radicle/src/cob/issue.rs index 8900bdba..447c89b5 100644 --- a/radicle/src/cob/issue.rs +++ b/radicle/src/cob/issue.rs @@ -129,7 +129,7 @@ impl store::FromHistory for Issue { let root = history.root(); // Deprecated. Remove when we drop legacy support. - if root.manifest().is_legacy() { + if root.manifest.is_legacy() { let legacy = super::legacy::issue::Issue::from_history(history, repo)?; let issue = legacy.into(); @@ -673,10 +673,10 @@ mod test { let mut issue_bob = bob_issues.get_mut(&id).unwrap(); issue_bob - .comment("Bob's reply", id.into(), vec![], &t.bob.signer) + .comment("Bob's reply", *id, vec![], &t.bob.signer) .unwrap(); issue_alice - .comment("Alice's reply", id.into(), vec![], &t.alice.signer) + .comment("Alice's reply", *id, vec![], &t.alice.signer) .unwrap(); assert_eq!(issue_bob.comments().count(), 2); @@ -704,7 +704,7 @@ mod test { t.eve.repo.fetch(&t.alice); let eve_reply = issue_eve - .comment("Eve's reply", id.into(), vec![], &t.eve.signer) + .comment("Eve's reply", *id, vec![], &t.eve.signer) .unwrap(); t.bob.repo.fetch(&t.eve); @@ -721,7 +721,7 @@ mod test { let (first, _) = issue_bob.comments().next().unwrap(); let (last, _) = issue_bob.comments().last().unwrap(); - assert_eq!(*first, issue_alice.id.into()); + assert_eq!(*first, *issue_alice.id); assert_eq!(*last, eve_reply); } @@ -1212,7 +1212,7 @@ mod test { issue .comment( "Here's a binary file", - issue.id.into(), + *issue.id, [embed3.clone()], &node.signer, ) diff --git a/radicle/src/cob/op.rs b/radicle/src/cob/op.rs index 758e93b6..c1524d5f 100644 --- a/radicle/src/cob/op.rs +++ b/radicle/src/cob/op.rs @@ -84,11 +84,11 @@ impl From for Op> { Self { id: *entry.id(), actions: entry.contents().clone(), - author: *entry.actor(), - parents: entry.parents().to_owned(), - timestamp: Timestamp::from_secs(entry.timestamp()), - identity: entry.resource(), - manifest: entry.manifest().clone(), + author: *entry.author(), + parents: entry.parents.to_owned(), + timestamp: Timestamp::from_secs(entry.timestamp), + identity: entry.resource, + manifest: entry.manifest.clone(), } } } @@ -101,13 +101,13 @@ where fn try_from(entry: &'a Entry) -> Result { let id = *entry.id(); - let identity = entry.resource(); + let identity = *entry.resource(); let actions: Vec<_> = entry .contents() .iter() .map(|blob| serde_json::from_slice(blob.as_slice())) .collect::>()?; - let manifest = entry.manifest().clone(); + let manifest = entry.manifest.clone(); // SAFETY: Entry is guaranteed to have at least one operation. #[allow(clippy::unwrap_used)] @@ -115,9 +115,9 @@ where let op = Op { id, actions, - author: *entry.actor(), - timestamp: Timestamp::from_secs(entry.timestamp()), - parents: entry.parents().to_owned(), + author: *entry.author(), + timestamp: Timestamp::from_secs(entry.timestamp), + parents: entry.parents.to_owned(), identity, manifest, }; diff --git a/radicle/src/cob/patch.rs b/radicle/src/cob/patch.rs index a5237ca5..2ed2126d 100644 --- a/radicle/src/cob/patch.rs +++ b/radicle/src/cob/patch.rs @@ -469,7 +469,7 @@ impl store::FromHistory for Patch { let root = history.root(); // Deprecated. Remove when we drop legacy support. - if root.manifest().is_legacy() { + if root.manifest.is_legacy() { let legacy = super::legacy::patch::Patch::from_history(history, repo)?; let patch = legacy.into(); @@ -1379,7 +1379,7 @@ where revision: RevisionId, signer: &G, ) -> Result { - if revision == RevisionId::from(self.id) { + if revision == RevisionId::from(*self.id) { return Err(Error::RootRevision(revision)); } self.transaction("Redact revision", signer, |tx| tx.redact(revision)) @@ -2223,7 +2223,7 @@ mod test { assert_eq!(patch.revisions().count(), 2); patch.redact(revision_id, &alice.signer).unwrap(); - assert_eq!(patch.latest().0, &RevisionId::from(patch_id)); + assert_eq!(patch.latest().0, &RevisionId::from(*patch_id)); assert_eq!(patch.revisions().count(), 1); // The patch's root must always exist. diff --git a/radicle/src/cob/test.rs b/radicle/src/cob/test.rs index 103ffef2..c39a9c02 100644 --- a/radicle/src/cob/test.rs +++ b/radicle/src/cob/test.rs @@ -2,6 +2,7 @@ use std::marker::PhantomData; use std::ops::Deref; use nonempty::NonEmpty; +use radicle_crypto::ssh::ExtendedSignature; use serde::{Deserialize, Serialize}; use crate::cob::op::Op; @@ -58,18 +59,24 @@ where { pub fn new(action: &T::Action, time: Timestamp, signer: &G) -> HistoryBuilder { let resource = arbitrary::oid(); + let revision = arbitrary::oid(); let (data, root) = encoded::(action, time, [], signer); let manifest = Manifest::new(T::type_name().clone(), Version::default()); + let signature = signer.sign(data.as_slice()); + let signature = ExtendedSignature::new(*signer.public_key(), signature); + let change = Entry { + id: root, + signature, + resource, + contents: NonEmpty::new(data), + timestamp: time.as_secs(), + revision, + parents: vec![], + manifest, + }; Self { - history: History::new_from_root( - root, - *signer.public_key(), - resource, - NonEmpty::new(data), - time.as_secs(), - manifest, - ), + history: History::new_from_root(change), time, resource, witness: PhantomData, @@ -87,18 +94,23 @@ where pub fn commit(&mut self, action: &T::Action, signer: &G) -> git::ext::Oid { let timestamp = self.time; let tips = self.tips(); + let revision = arbitrary::oid(); let (data, oid) = encoded::(action, timestamp, tips, signer); let manifest = Manifest::new(T::type_name().clone(), Version::default()); - - self.history.extend( - oid, - *signer.public_key(), - self.resource, - NonEmpty::new(data), - vec![], - timestamp.as_secs(), + let signature = signer.sign(data.as_slice()); + let signature = ExtendedSignature::new(*signer.public_key(), signature); + let change = Entry { + id: oid, + signature, + resource: self.resource, + contents: NonEmpty::new(data), + timestamp: timestamp.as_secs(), + revision, + parents: vec![], manifest, - ); + }; + self.history.extend(change); + oid } } diff --git a/radicle/src/storage/git/cob.rs b/radicle/src/storage/git/cob.rs index eb58e635..7a1858c5 100644 --- a/radicle/src/storage/git/cob.rs +++ b/radicle/src/storage/git/cob.rs @@ -58,14 +58,14 @@ impl change::Storage for Repository { parents: Vec, signer: &Signer, spec: change::Template, - ) -> Result + ) -> Result where Signer: crypto::Signer, { self.backend.store(authority, parents, signer, spec) } - fn load(&self, id: Self::ObjectId) -> Result { + fn load(&self, id: Self::ObjectId) -> Result { self.backend.load(id) } @@ -139,7 +139,7 @@ impl cob::object::Storage for Repository { identifier: &Self::Identifier, typename: &cob::TypeName, object_id: &cob::ObjectId, - change: &cob::Change, + change: &cob::Entry, ) -> Result<(), Self::UpdateError> { self.backend.reference( git::refs::storage::cob(identifier, typename, object_id).as_str(), @@ -202,14 +202,14 @@ impl<'a> change::Storage for DraftStore<'a> { parents: Vec, signer: &Signer, spec: change::Template, - ) -> Result + ) -> Result where Signer: crypto::Signer, { self.repo.backend.store(authority, parents, signer, spec) } - fn load(&self, id: Self::ObjectId) -> Result { + fn load(&self, id: Self::ObjectId) -> Result { self.repo.backend.load(id) } @@ -387,7 +387,7 @@ impl<'a> cob::object::Storage for DraftStore<'a> { identifier: &Self::Identifier, typename: &cob::TypeName, object_id: &cob::ObjectId, - change: &cob::Change, + change: &cob::Entry, ) -> Result<(), Self::UpdateError> { self.repo.backend.reference( git::refs::storage::draft::cob(identifier, typename, object_id).as_str(), diff --git a/radicle/src/test/arbitrary.rs b/radicle/src/test/arbitrary.rs index 9c776699..84bebdbc 100644 --- a/radicle/src/test/arbitrary.rs +++ b/radicle/src/test/arbitrary.rs @@ -28,7 +28,7 @@ pub fn oid() -> storage::Oid { } pub fn entry_id() -> cob::EntryId { - self::oid().into() + self::oid() } pub fn refstring(len: usize) -> git::RefString {