diff --git a/radicle-cli/src/commands/patch/edit.rs b/radicle-cli/src/commands/patch/edit.rs index 047b9147..b7497555 100644 --- a/radicle-cli/src/commands/patch/edit.rs +++ b/radicle-cli/src/commands/patch/edit.rs @@ -44,7 +44,7 @@ pub fn run( tx.edit(t, target)?; } if let Some(d) = description { - tx.edit_revision(root, d)?; + tx.edit_revision(root, d, Vec::default())?; } Ok(()) })?; diff --git a/radicle/src/cob/patch.rs b/radicle/src/cob/patch.rs index a3c38be5..715756bb 100644 --- a/radicle/src/cob/patch.rs +++ b/radicle/src/cob/patch.rs @@ -5,6 +5,7 @@ use std::ops::Deref; use std::str::FromStr; use amplify::Wrapper; +use nonempty::NonEmpty; use once_cell::sync::Lazy; use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize}; @@ -17,7 +18,7 @@ use crate::cob::store::Transaction; use crate::cob::store::{Cob, CobAction}; use crate::cob::thread; use crate::cob::thread::Thread; -use crate::cob::thread::{Comment, CommentId, Reactions}; +use crate::cob::thread::{Comment, CommentId, Edit, Reactions}; use crate::cob::{op, store, ActorId, Embed, EntryId, ObjectId, TypeName, Uri}; use crate::crypto::{PublicKey, Signer}; use crate::git; @@ -218,6 +219,9 @@ pub enum Action { RevisionEdit { revision: RevisionId, description: String, + /// Embeded content. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + embeds: Vec>, }, /// React to the revision. #[serde(rename = "revision.react")] @@ -732,11 +736,17 @@ impl Patch { Action::RevisionEdit { revision, description, + embeds, } => { if let Some(redactable) = self.revisions.get_mut(&revision) { // If the revision was redacted concurrently, there's nothing to do. if let Some(revision) = redactable { - revision.description = description; + revision.description.push(Edit::new( + author, + description, + timestamp, + embeds, + )); } } else { return Err(Error::Missing(revision.into_inner())); @@ -1247,7 +1257,7 @@ pub struct Revision { /// Author of the revision. pub(super) author: Author, /// Revision description. - pub(super) description: String, + pub(super) description: NonEmpty, /// Base branch commit, used as a merge base. pub(super) base: git::Oid, /// Reference to the Git object containing the code (revision head). @@ -1273,9 +1283,11 @@ impl Revision { timestamp: Timestamp, resolves: BTreeSet<(EntryId, CommentId)>, ) -> Self { + let description = Edit::new(*author.public_key(), description, timestamp, Vec::default()); + Self { author, - description, + description: NonEmpty::new(description), base, oid, discussion: Thread::default(), @@ -1287,7 +1299,7 @@ impl Revision { } pub fn description(&self) -> &str { - self.description.as_str() + self.description.last().body.as_str() } /// Author of the revision. @@ -1496,10 +1508,15 @@ impl store::Transaction { &mut self, revision: RevisionId, description: impl ToString, + embeds: Vec, ) -> Result<(), store::Error> { + let hashed = embeds.iter().map(|e| e.hashed()).collect(); + + self.embed(embeds)?; self.push(Action::RevisionEdit { revision, description: description.to_string(), + embeds: hashed, }) } @@ -1806,10 +1823,11 @@ where &mut self, revision: RevisionId, description: String, + embeds: impl IntoIterator, signer: &G, ) -> Result { self.transaction("Edit revision", signer, |tx| { - tx.edit_revision(revision, description) + tx.edit_revision(revision, description, embeds.into_iter().collect()) }) } @@ -2621,6 +2639,7 @@ mod test { &Action::RevisionEdit { revision: RevisionId(*h0.root().id()), description: String::from("Edited"), + embeds: Vec::default(), }, &bob, ); diff --git a/radicle/src/cob/thread.rs b/radicle/src/cob/thread.rs index f67eb24a..f8683320 100644 --- a/radicle/src/cob/thread.rs +++ b/radicle/src/cob/thread.rs @@ -66,6 +66,23 @@ pub struct Edit { pub embeds: Vec>, } +impl Edit { + /// Create a new edit. + pub fn new( + author: ActorId, + body: String, + timestamp: Timestamp, + embeds: Vec>, + ) -> Self { + Self { + author, + timestamp, + body, + embeds, + } + } +} + /// A comment on a discussion thread. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Comment { @@ -123,12 +140,7 @@ impl Comment { embeds: Vec>, timestamp: Timestamp, ) -> Self { - let edit = Edit { - author, - body, - embeds, - timestamp, - }; + let edit = Edit::new(author, body, timestamp, embeds); Self { author, @@ -180,12 +192,7 @@ impl Comment { embeds: Vec>, timestamp: Timestamp, ) { - self.edits.push(Edit { - author, - body, - embeds, - timestamp, - }); + self.edits.push(Edit::new(author, body, timestamp, embeds)); } /// Comment reactions.