From 2ca1e74707c8378c377e283428a048063042ca79 Mon Sep 17 00:00:00 2001 From: cloudhead Date: Mon, 6 May 2024 13:34:23 +0200 Subject: [PATCH] cli: Have way to delete payload field in `rad id` Allow for deleting a field by setting it to `null`. --- rad-id.1.adoc | 2 +- .../examples/rad-id-update-delete-field.md | 71 +++++++++++++++++++ radicle-cli/src/commands/id.rs | 6 +- radicle-cli/tests/commands.rs | 27 +++++++ 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 radicle-cli/examples/rad-id-update-delete-field.md diff --git a/rad-id.1.adoc b/rad-id.1.adoc index a1ac089b..124bc26f 100644 --- a/rad-id.1.adoc +++ b/rad-id.1.adoc @@ -76,7 +76,7 @@ automatically accepted and included into the identity document. *--payload* _ _:: Update the identity by setting metadata in one of the identity payloads. This can be used to update a repository's project name or description, for - example. + example. To delete a field from a payload, simply set it to *null*. *--no-confirm*:: Don't ask for confirmation before creating the revision. diff --git a/radicle-cli/examples/rad-id-update-delete-field.md b/radicle-cli/examples/rad-id-update-delete-field.md new file mode 100644 index 00000000..548cc9c6 --- /dev/null +++ b/radicle-cli/examples/rad-id-update-delete-field.md @@ -0,0 +1,71 @@ +Let's add a payload field and then delete it. + +``` +$ rad id update --title "Add field" --description "Add a new 'web' field" --payload xyz.radicle.project web '"https://acme.example"' +✓ Identity revision a8a9fee6c4f83578ab132d375f1da0c81282bef3 created +╭───────────────────────────────────────────────────────────────────╮ +│ Title Add field │ +│ Revision a8a9fee6c4f83578ab132d375f1da0c81282bef3 │ +│ Blob fbe268d13e60f1f3a1972e0ccd592f3cdecf08b5 │ +│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │ +│ State accepted │ +│ Quorum yes │ +│ │ +│ Add a new 'web' field │ +├───────────────────────────────────────────────────────────────────┤ +│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) │ +╰───────────────────────────────────────────────────────────────────╯ + +@@ -1,13 +1,14 @@ + { + "payload": { + "xyz.radicle.project": { + "defaultBranch": "master", + "description": "Radicle Heartwood Protocol & Stack", +- "name": "heartwood" ++ "name": "heartwood", ++ "web": "https://acme.example" + } + }, + "delegates": [ + "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" + ], + "threshold": 1 + } +``` + +Now let's delete it by setting it to `null`. + +``` +$ rad id update --title "Delete field" --description "Delete 'web'" --payload xyz.radicle.project web null +✓ Identity revision d373c35876833105f8aafed8b610660b5737cd67 created +╭───────────────────────────────────────────────────────────────────╮ +│ Title Delete field │ +│ Revision d373c35876833105f8aafed8b610660b5737cd67 │ +│ Blob d96f425412c9f8ad5d9a9a05c9831d0728e2338d │ +│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │ +│ State accepted │ +│ Quorum yes │ +│ │ +│ Delete 'web' │ +├───────────────────────────────────────────────────────────────────┤ +│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) │ +╰───────────────────────────────────────────────────────────────────╯ + +@@ -1,14 +1,13 @@ + { + "payload": { + "xyz.radicle.project": { + "defaultBranch": "master", + "description": "Radicle Heartwood Protocol & Stack", +- "name": "heartwood", +- "web": "https://acme.example" ++ "name": "heartwood" + } + }, + "delegates": [ + "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi" + ], + "threshold": 1 + } +``` diff --git a/radicle-cli/src/commands/id.rs b/radicle-cli/src/commands/id.rs index d1f4d4b6..f2333ee8 100644 --- a/radicle-cli/src/commands/id.rs +++ b/radicle-cli/src/commands/id.rs @@ -378,7 +378,11 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { for (id, key, val) in payload { if let Some(ref mut payload) = proposal.payload.get_mut(&id) { if let Some(obj) = payload.as_object_mut() { - obj.insert(key, val); + if val.is_null() { + obj.remove(&key); + } else { + obj.insert(key, val); + } } else { anyhow::bail!("payload `{id}` is not a map"); } diff --git a/radicle-cli/tests/commands.rs b/radicle-cli/tests/commands.rs index e09d5553..f31333b1 100644 --- a/radicle-cli/tests/commands.rs +++ b/radicle-cli/tests/commands.rs @@ -418,6 +418,33 @@ fn rad_id_threshold() { .unwrap(); } +#[test] +fn rad_id_update_delete_field() { + let mut environment = Environment::new(); + let alice = environment.node(config::node("alice")); + let working = tempfile::tempdir().unwrap(); + let working = working.path(); + + // Setup a test repository. + fixtures::repository(working.join("alice")); + + test( + "examples/rad-init.md", + working.join("alice"), + Some(&alice.home), + [], + ) + .unwrap(); + + test( + "examples/rad-id-update-delete-field.md", + working.join("alice"), + Some(&alice.home), + [], + ) + .unwrap(); +} + #[test] fn rad_id_multi_delegate() { let mut environment = Environment::new();