From 0fb1128bd319155d400f463eb45aaffd7fa07d1a Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Wed, 22 Nov 2023 14:14:11 +0000 Subject: [PATCH] cli: rework `rad rm` as `rad clean` Removing a repository completely can result in data corruption for users, since a user's `rad/sigrefs` are the ground truth of their state, and any fork of them results in errors in the protocol. Instead of `rad rm`, we replace it with `rad clean` that removes all remotes other than the local peer's namespace and the delegates'. The delegates are also necessary to keep, since the repository's identity is dependent on them. Note that the remotes that were cleaned will be populated again upon fetching, as long as they are tracked. Signed-off-by: Fintan Halpenny X-Clacks-Overhead: GNU Terry Pratchett --- radicle-cli/examples/rad-clean.md | 58 +++++++++++++++++ radicle-cli/examples/rad-rm.md | 33 ---------- radicle-cli/src/commands.rs | 4 +- radicle-cli/src/commands/{rm.rs => clean.rs} | 66 +++++--------------- radicle-cli/src/commands/help.rs | 2 +- radicle-cli/src/main.rs | 8 ++- radicle-cli/tests/commands.rs | 46 +++++++++++--- 7 files changed, 120 insertions(+), 97 deletions(-) create mode 100644 radicle-cli/examples/rad-clean.md delete mode 100644 radicle-cli/examples/rad-rm.md rename radicle-cli/src/commands/{rm.rs => clean.rs} (50%) diff --git a/radicle-cli/examples/rad-clean.md b/radicle-cli/examples/rad-clean.md new file mode 100644 index 00000000..63d0cfe3 --- /dev/null +++ b/radicle-cli/examples/rad-clean.md @@ -0,0 +1,58 @@ +We cannot delete a repository, since that can cause data integrity +issues. However, we can clean the storage of remotes that are not the +local peer or the repository delegates. To do this we can use the `rad +clean` command. + +First let's look at what we have locally: + +``` +$ rad ls +╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Name RID Visibility Head Description │ +├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +Let's also inspect what remotes are in the repository: + +``` +$ rad inspect --sigrefs +z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi f209c9f68aa689af24220a20462e13ee9dfb2a95 +z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk 161b775a3509c8098de67f57f750972bba015b31 +``` + +Now let's clean the `heartwood` project: + +``` +$ rad clean rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm +Removed z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk +✓ Successfully cleaned rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji +``` + +Inspecting the remotes again, we see that Bob is now gone: + +``` +$ rad inspect --sigrefs +z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi f209c9f68aa689af24220a20462e13ee9dfb2a95 +``` + +Note that Bob will be fetched again if we do not untrack his +node. Currently, there is no per repository tracking so it's not +possible to stop fetching Bob for this particular repository. + +Cleaning a repository again will remove no remotes, since we're +already at the minimal set of remotes: + +``` +$ rad clean rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm +✓ Successfully cleaned rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji +``` + +And attempting to clean a non-existent repository has no effect on the +storage at all: + +``` (fail) +$ rad clean rad:z42hL2jL4XNk6K8oHQaSWdeadbeef --no-confirm +✗ Error: repository rad:z42hL2jL4XNk6K8oHQaSWdeadbeef was not found +``` diff --git a/radicle-cli/examples/rad-rm.md b/radicle-cli/examples/rad-rm.md deleted file mode 100644 index f4e554b2..00000000 --- a/radicle-cli/examples/rad-rm.md +++ /dev/null @@ -1,33 +0,0 @@ -To delete a repository from local storage, we use the `rad rm` command. -First let's look at what we have locally: - -``` -$ rad ls -╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -│ Name RID Visibility Head Description │ -├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ -│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │ -╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -``` - -Now let's delete the `heartwood` project: - -``` -$ rad rm rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm -✓ Untracked rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji -✓ Successfully removed 'rad' remote -✓ Successfully removed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from storage -``` - -We can check our repositories again to see if it was deleted: - -``` -$ rad ls -``` - -Attempting to remove a repository that doesn't exist gives us an error message: - -``` (fail) -$ rad rm rad:z2Jk1mNqyX7AjT4K83jJW9vQoHn4f -✗ Error: repository rad:z2Jk1mNqyX7AjT4K83jJW9vQoHn4f was not found -``` diff --git a/radicle-cli/src/commands.rs b/radicle-cli/src/commands.rs index 3eea8ec4..6b9d6021 100644 --- a/radicle-cli/src/commands.rs +++ b/radicle-cli/src/commands.rs @@ -4,6 +4,8 @@ pub mod rad_assign; pub mod rad_auth; #[path = "commands/checkout.rs"] pub mod rad_checkout; +#[path = "commands/clean.rs"] +pub mod rad_clean; #[path = "commands/clone.rs"] pub mod rad_clone; #[path = "commands/cob.rs"] @@ -38,8 +40,6 @@ pub mod rad_publish; pub mod rad_remote; #[path = "commands/review.rs"] pub mod rad_review; -#[path = "commands/rm.rs"] -pub mod rad_rm; #[path = "commands/self.rs"] pub mod rad_self; #[path = "commands/sync.rs"] diff --git a/radicle-cli/src/commands/rm.rs b/radicle-cli/src/commands/clean.rs similarity index 50% rename from radicle-cli/src/commands/rm.rs rename to radicle-cli/src/commands/clean.rs index 2675db04..1e087423 100644 --- a/radicle-cli/src/commands/rm.rs +++ b/radicle-cli/src/commands/clean.rs @@ -3,26 +3,26 @@ use std::ffi::OsString; use anyhow::anyhow; use radicle::identity::Id; -use radicle::node; -use radicle::node::Handle as _; use radicle::storage; use radicle::storage::WriteStorage; -use radicle::Profile; -use crate::git; use crate::terminal as term; use crate::terminal::args::{Args, Error, Help}; pub const HELP: Help = Help { - name: "rm", - description: "Remove a project", + name: "clean", + description: "Clean a project", version: env!("CARGO_PKG_VERSION"), usage: r#" Usage - rad rm [