From c63aaaceac5cc3b077b53bb517536e26e567a930 Mon Sep 17 00:00:00 2001 From: cloudhead Date: Fri, 23 Feb 2024 11:35:54 +0100 Subject: [PATCH] cli: Fix `id` COB notifications in `rad inbox` --- radicle-cli/examples/rad-inbox.md | 32 ++++++++++++++++++++++++++++++ radicle-cli/src/commands/inbox.rs | 31 +++++++++++++++++++++++++++-- radicle-cli/src/terminal/format.rs | 16 +++++++++++++++ radicle-node/src/worker/fetch.rs | 5 +++++ radicle/src/node/notifications.rs | 7 ++++--- 5 files changed, 86 insertions(+), 5 deletions(-) diff --git a/radicle-cli/examples/rad-inbox.md b/radicle-cli/examples/rad-inbox.md index fb75d4f3..43f72e4d 100644 --- a/radicle-cli/examples/rad-inbox.md +++ b/radicle-cli/examples/rad-inbox.md @@ -106,3 +106,35 @@ $ rad inbox clear --all $ rad inbox clear --all Your inbox is empty. ``` + +Now let's do an identity update. + +``` ~alice +$ rad id update --title "Modify description" --description "Use website" --payload xyz.radicle.project description '"https://radicle.xyz"' -q +[..] +$ rad sync -a +✓ Synced with 1 node(s) +``` + +``` ~bob +$ rad inbox --all +╭──────────────────────────────────────────────────────────────────────╮ +│ heartwood │ +├──────────────────────────────────────────────────────────────────────┤ +│ 001 ● [ ... ] Modify description id accepted alice now │ +╰──────────────────────────────────────────────────────────────────────╯ +$ rad inbox show 1 +{ + "payload": { + "xyz.radicle.project": { + "defaultBranch": "master", + "description": "https://radicle.xyz", + "name": "heartwood" + } + }, + "delegates": [ + "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" + ], + "threshold": 1 +} +``` diff --git a/radicle-cli/src/commands/inbox.rs b/radicle-cli/src/commands/inbox.rs index 702676c5..2997765c 100644 --- a/radicle-cli/src/commands/inbox.rs +++ b/radicle-cli/src/commands/inbox.rs @@ -1,9 +1,11 @@ use std::ffi::OsString; +use std::path::Path; use std::process; use anyhow::anyhow; use localtime::LocalTime; +use radicle::identity::Identity; use radicle::issue::Issues; use radicle::node::notifications; use radicle::node::notifications::*; @@ -298,6 +300,26 @@ where patch.title().to_owned(), term::format::patch::state(patch.state()), ) + } else if type_name == *cob::identity::TYPENAME { + let Ok(identity) = Identity::get(&id, &repo) else { + log::error!( + target: "cli", + "Error retrieving identity {id} for notification {}", n.id + ); + continue; + }; + let Some(rev) = n.update.new().and_then(|id| identity.revision(&id)) else { + log::error!( + target: "cli", + "Error retrieving identity revision for notification {}", n.id + ); + continue; + }; + ( + String::from("id"), + rev.title.clone(), + term::format::identity::state(&rev.state), + ) } else { ( type_name.to_string(), @@ -395,6 +417,11 @@ fn show( term::patch::show(&patch, &id, false, &repo, None, profile)?; } + NotificationKind::Cob { type_name, id } if type_name == *cob::identity::TYPENAME => { + let identity = Identity::get(&id, &repo)?; + + term::json::to_pretty(&identity.doc, Path::new("radicle.json"))?.print(); + } NotificationKind::Branch { .. } => { let refstr = if let Some(remote) = n.remote { n.qualified @@ -409,8 +436,8 @@ fn show( .spawn()? .wait()?; } - _ => { - todo!(); + notification => { + term::json::to_pretty(¬ification, Path::new("notification.json"))?.print(); } } notifs.set_status(NotificationStatus::ReadAt(LocalTime::now()), &[id])?; diff --git a/radicle-cli/src/terminal/format.rs b/radicle-cli/src/terminal/format.rs index a66c81c6..23dfb49f 100644 --- a/radicle-cli/src/terminal/format.rs +++ b/radicle-cli/src/terminal/format.rs @@ -277,6 +277,22 @@ pub mod patch { } } +/// Identity formatting +pub mod identity { + use super::*; + use radicle::cob::identity::State; + + /// Format identity revision state. + pub fn state(s: &State) -> term::Paint { + match s { + State::Active { .. } => term::format::tertiary(s.to_string()), + State::Accepted { .. } => term::format::positive(s.to_string()), + State::Rejected { .. } => term::format::negative(s.to_string()), + State::Stale { .. } => term::format::dim(s.to_string()), + } + } +} + #[cfg(test)] mod test { use super::*; diff --git a/radicle-node/src/worker/fetch.rs b/radicle-node/src/worker/fetch.rs index 83212afb..0dc290b6 100644 --- a/radicle-node/src/worker/fetch.rs +++ b/radicle-node/src/worker/fetch.rs @@ -170,6 +170,11 @@ fn notify( // Don't notify about signed refs. continue; } + if r == *git::refs::storage::IDENTITY_BRANCH { + // Don't notify about the peers's identity branch pointer, since there will + // be a separate notification on the identity COB itself. + continue; + } if let Some(rest) = r.strip_prefix(git::refname!("refs/heads/patches")) { if radicle::cob::ObjectId::from_str(rest.as_str()).is_ok() { // Don't notify about patch branches, since we already get diff --git a/radicle/src/node/notifications.rs b/radicle/src/node/notifications.rs index 267254db..a1ae9055 100644 --- a/radicle/src/node/notifications.rs +++ b/radicle/src/node/notifications.rs @@ -1,6 +1,7 @@ pub mod store; use localtime::LocalTime; +use serde::Serialize; use sqlite as sql; use thiserror::Error; @@ -19,7 +20,7 @@ pub type StoreReader = Store; /// Unique identifier for a notification. pub type NotificationId = u32; -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize)] pub enum NotificationStatus { ReadAt(LocalTime), Unread, @@ -32,7 +33,7 @@ impl NotificationStatus { } /// A notification for an updated ref. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize)] pub struct Notification { /// Unique notification ID. pub id: NotificationId, @@ -53,7 +54,7 @@ pub struct Notification { } /// Type of notification. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize)] pub enum NotificationKind { /// A COB changed. Cob { type_name: TypeName, id: ObjectId },