Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include tooling removal methods #69

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
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.
CompeyDev marked this conversation as resolved.
Show resolved Hide resolved

If the tool does not exist, this will return `false` and do nothing.
CompeyDev marked this conversation as resolved.
Show resolved Hide resolved
*/
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
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.
CompeyDev marked this conversation as resolved.
Show resolved Hide resolved
#[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.
CompeyDev marked this conversation as resolved.
Show resolved Hide resolved
#[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();
}
CompeyDev marked this conversation as resolved.
Show resolved Hide resolved

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