Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions lib/manifests/rokit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,27 @@ impl RokitManifest {
}
}

/**
Removes a tool to the manifest.
Comment thread
CompeyDev marked this conversation as resolved.
Outdated

If the tool does not exist, this will return `false` and do nothing.
Comment thread
CompeyDev marked this conversation as resolved.
Outdated
*/
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.

Expand Down
16 changes: 16 additions & 0 deletions lib/storage/tool_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
4 changes: 4 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use anyhow::{Context, Result};
use clap::{ArgAction, CommandFactory, Parser};
use remove::RemoveSubcommand;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this was an auto import, so rust-analyzer put it up here, but all the imports for commands are grouped below so the new import should be there as well.

use tokio::time::Instant;
use tracing::level_filters::LevelFilter;

Expand All @@ -13,6 +14,7 @@ mod authenticate;
mod init;
mod install;
mod list;
mod remove;
mod self_install;
mod self_update;
mod system_info;
Expand Down Expand Up @@ -123,6 +125,7 @@ pub enum Subcommand {
SystemInfo(SystemInfoSubcommand),
Trust(TrustSubcommand),
Update(UpdateSubcommand),
Remove(RemoveSubcommand),
}

impl Subcommand {
Expand All @@ -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,
}
}
}
Expand Down
87 changes: 87 additions & 0 deletions src/cli/remove.rs
Original file line number Diff line number Diff line change
@@ -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.
Comment thread
CompeyDev marked this conversation as resolved.
Outdated
#[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.
Comment thread
CompeyDev marked this conversation as resolved.
Outdated
#[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();
}
Comment thread
CompeyDev marked this conversation as resolved.
Outdated

// 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(())
}
}