From 15db8c9b2f0e16e096fc36192a5edb0fb4b12b09 Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Sat, 17 Aug 2024 11:26:57 +0530 Subject: [PATCH 1/7] feat: include tooling removal methods * Added `RokitManifest::remove_tool` to remove a tool from the manifests * Added `ToolStorage::remove_tool_link` to remove a link for an installed tool --- lib/manifests/rokit.rs | 21 +++++++++++++++++++++ lib/storage/tool_storage.rs | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/lib/manifests/rokit.rs b/lib/manifests/rokit.rs index c602d55..2485e99 100644 --- a/lib/manifests/rokit.rs +++ b/lib/manifests/rokit.rs @@ -132,6 +132,27 @@ impl RokitManifest { } } + /** + Removes a tool to the manifest. + + If the tool does not exist, this will return `false` and do nothing. + */ + pub fn remove_tool(&mut self, alias: &ToolAlias) -> bool { + let doc = self.document.as_table_mut(); + + if let Some(tools) = doc.get_mut("tools") { + let tools = tools.as_table_mut().unwrap(); + if tools.contains_key(alias.name()) { + tools.remove(alias.name()); + true + } else { + false + } + } else { + false + } + } + /** Updates a tool in the manifest with a new tool specification. diff --git a/lib/storage/tool_storage.rs b/lib/storage/tool_storage.rs index aae1528..1002009 100644 --- a/lib/storage/tool_storage.rs +++ b/lib/storage/tool_storage.rs @@ -137,6 +137,22 @@ impl ToolStorage { Ok(()) } + /** + Removes a link for a given tool. + + # Errors + + - If the link could not be removed. + */ + pub async fn remove_tool_link(&self, alias: &ToolAlias) -> RokitResult<()> { + let path = self.alias_path(alias); + if path_exists(&path).await { + remove_file(&path).await?; + } + + Ok(()) + } + /** Reads all currently known link paths for tool aliases in the binary directory. From ad297cd8bec48a2e38d2e25c847a74f0dd8dc13f Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Sat, 17 Aug 2024 11:30:04 +0530 Subject: [PATCH 2/7] feat(cli): add remove subcommand --- src/cli/mod.rs | 4 +++ src/cli/remove.rs | 87 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/cli/remove.rs diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 5959537..d382089 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,5 +1,6 @@ use anyhow::{Context, Result}; use clap::{ArgAction, CommandFactory, Parser}; +use remove::RemoveSubcommand; use tokio::time::Instant; use tracing::level_filters::LevelFilter; @@ -13,6 +14,7 @@ mod authenticate; mod init; mod install; mod list; +mod remove; mod self_install; mod self_update; mod system_info; @@ -123,6 +125,7 @@ pub enum Subcommand { SystemInfo(SystemInfoSubcommand), Trust(TrustSubcommand), Update(UpdateSubcommand), + Remove(RemoveSubcommand), } impl Subcommand { @@ -138,6 +141,7 @@ impl Subcommand { Self::SystemInfo(cmd) => cmd.run(home).await, Self::Trust(cmd) => cmd.run(home).await, Self::Update(cmd) => cmd.run(home).await, + Self::Remove(cmd) => cmd.run(home).await, } } } diff --git a/src/cli/remove.rs b/src/cli/remove.rs new file mode 100644 index 0000000..4a46c8a --- /dev/null +++ b/src/cli/remove.rs @@ -0,0 +1,87 @@ +use anyhow::{bail, Context, Result}; +use clap::Parser; +use console::style; + +use rokit::{ + discovery::discover_all_manifests, manifests::RokitManifest, storage::Home, tool::ToolAlias, +}; + +use crate::util::CliProgressTracker; + +/// Adds a new tool to Rokit and installs it. +#[derive(Debug, Parser)] +pub struct RemoveSubcommand { + /// The alias of the tool to remove. + pub alias: ToolAlias, + /// Remove this tool globally instead of adding + /// it to the nearest manifest file. + #[clap(long)] + pub global: bool, +} + +impl RemoveSubcommand { + pub async fn run(self, home: &Home) -> Result<()> { + let tool_cache = home.tool_cache(); + let tool_storage = home.tool_storage(); + + // 1. Load the manifest and check whether the tool + // to be removed is present in the manifest + let manifest_path = if self.global { + home.path().to_path_buf() + } else { + let non_global_manifests = discover_all_manifests(true, true).await; + non_global_manifests + .first() + .map(|m| m.path.parent().unwrap().to_path_buf()) + .context( + "No manifest was found for the current directory.\ + \nRun `rokit init` in your project root to create one.", + )? + }; + + let mut manifest = if self.global { + RokitManifest::load_or_create(&manifest_path).await? + } else { + RokitManifest::load(&manifest_path).await? + }; + if !manifest.has_tool(&self.alias) { + bail!("Tool does not exist and can't be removed: {}", self.alias); + } + + // 2. Remove the tool from the manifest + let spec = manifest.get_tool(&self.alias).unwrap(); + let pt = CliProgressTracker::new_with_message("Removing", 2); + + manifest.remove_tool(&self.alias); + manifest.save(manifest_path).await?; + pt.task_completed(); + + // 3. Uninstall the tool link + if tool_cache.is_installed(&spec) { + pt.update_message("Uninstalling"); + tool_storage.remove_tool_link(&self.alias).await?; + pt.task_completed(); + } else { + pt.task_completed(); + pt.task_completed(); + } + + // 3. Finally, display a nice message to the user + pt.finish_with_message(format!( + "Removed version {} of tool {}{} {}", + style(spec.version()).bold().yellow(), + style(spec.name()).bold().magenta(), + if self.alias.name() == spec.id().name() { + String::new() + } else { + format!( + " with alias {}", + style(self.alias.to_string()).bold().cyan() + ) + }, + pt.formatted_elapsed(), + )); + + Ok(()) + } +} From fe2bb285958442124178cad759a7e159de335df6 Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Wed, 28 Aug 2024 11:06:11 +0530 Subject: [PATCH 3/7] doc: fix incorrect doc comments (x1) Co-authored-by: Filip Tibell --- src/cli/remove.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/remove.rs b/src/cli/remove.rs index 4a46c8a..792b106 100644 --- a/src/cli/remove.rs +++ b/src/cli/remove.rs @@ -13,8 +13,8 @@ use crate::util::CliProgressTracker; pub struct RemoveSubcommand { /// The alias of the tool to remove. pub alias: ToolAlias, - /// Remove this tool globally instead of adding - /// it to the nearest manifest file. + /// Remove this tool globally instead of removing + /// it from the nearest manifest file. #[clap(long)] pub global: bool, } From 8519155788221133a2f235493484911e6d4fd450 Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Wed, 28 Aug 2024 11:06:19 +0530 Subject: [PATCH 4/7] doc: fix incorrect doc comments (x2) Co-authored-by: Filip Tibell --- lib/manifests/rokit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/manifests/rokit.rs b/lib/manifests/rokit.rs index 2485e99..0453240 100644 --- a/lib/manifests/rokit.rs +++ b/lib/manifests/rokit.rs @@ -133,7 +133,7 @@ impl RokitManifest { } /** - Removes a tool to the manifest. + Removes a tool from the manifest. If the tool does not exist, this will return `false` and do nothing. */ From 8ec3f8c889582e4a2899683cab9c081e19f2d50c Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Wed, 28 Aug 2024 11:06:28 +0530 Subject: [PATCH 5/7] doc: fix incorrect doc comments (x3) Co-authored-by: Filip Tibell --- src/cli/remove.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/remove.rs b/src/cli/remove.rs index 792b106..d092b77 100644 --- a/src/cli/remove.rs +++ b/src/cli/remove.rs @@ -8,7 +8,7 @@ use rokit::{ use crate::util::CliProgressTracker; -/// Adds a new tool to Rokit and installs it. +/// Removes a tool from Rokit. #[derive(Debug, Parser)] pub struct RemoveSubcommand { /// The alias of the tool to remove. From 8032c53062b331a8b02a757b364534b0484640e8 Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Wed, 28 Aug 2024 11:06:48 +0530 Subject: [PATCH 6/7] doc: fix incorrect doc comments (x4) Co-authored-by: Filip Tibell --- lib/manifests/rokit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/manifests/rokit.rs b/lib/manifests/rokit.rs index 0453240..1d0bb6f 100644 --- a/lib/manifests/rokit.rs +++ b/lib/manifests/rokit.rs @@ -135,7 +135,7 @@ impl RokitManifest { /** Removes a tool from the manifest. - If the tool does not exist, this will return `false` and do nothing. + If the tool did not exist, this will return `false` and do nothing. */ pub fn remove_tool(&mut self, alias: &ToolAlias) -> bool { let doc = self.document.as_table_mut(); From 43e9f4eb61cfc897a82437957af22cc4d12cda3c Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Wed, 28 Aug 2024 11:07:17 +0530 Subject: [PATCH 7/7] fix(cli): incorrect number of progress updates Co-authored-by: Filip Tibell --- src/cli/remove.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cli/remove.rs b/src/cli/remove.rs index d092b77..bca4141 100644 --- a/src/cli/remove.rs +++ b/src/cli/remove.rs @@ -60,11 +60,8 @@ impl RemoveSubcommand { if tool_cache.is_installed(&spec) { pt.update_message("Uninstalling"); tool_storage.remove_tool_link(&self.alias).await?; - pt.task_completed(); - } else { - pt.task_completed(); - pt.task_completed(); } + pt.task_completed(); // 3. Finally, display a nice message to the user pt.finish_with_message(format!(