diff --git a/src/args.rs b/src/args.rs index 10d34a6..a375279 100644 --- a/src/args.rs +++ b/src/args.rs @@ -28,6 +28,10 @@ pub enum Command { #[command()] Install(InstallArgs), + /// Uninstalls the given node version + #[command()] + Uninstall(UninstallArgs), + /// Sets the specified version as the global default #[command()] Default(DefaultArgs), @@ -69,6 +73,12 @@ pub struct InstallArgs { pub version: NodeVersion, } +#[derive(Clone, Debug, Parser)] +pub struct UninstallArgs { + /// the version to install + pub version: NodeVersion, +} + #[derive(Clone, Debug, Parser)] pub struct DefaultArgs { /// The version to set as default diff --git a/src/main.rs b/src/main.rs index 3d313d9..1ec8a0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,7 @@ async fn main() -> Result<()> { match args.command { args::Command::Install(v) => nenv.install(v.version).await, + args::Command::Uninstall(v) => nenv.uninstall(v.version).await, args::Command::Default(v) => nenv.set_system_default(v.version).await, args::Command::Exec(args) => { let exit_code = nenv.exec(args.command, args.args).await?; diff --git a/src/nenv.rs b/src/nenv.rs index d59614e..2bbb683 100644 --- a/src/nenv.rs +++ b/src/nenv.rs @@ -62,6 +62,24 @@ impl Nenv { } } + #[tracing::instrument(skip(self))] + pub async fn uninstall(&mut self, version: NodeVersion) -> Result<()> { + if prompt( + false, + format!( + "Do you really want to uninstall node {}?", + version.to_string().bold() + ), + ) { + self.repo.uninstall(&version).await?; + println!("Node {} has been removed.", version.to_string().bold()) + } else { + println!("Nothing changed."); + } + + Ok(()) + } + /// Sets the system-wide default version #[tracing::instrument(skip(self))] pub async fn set_system_default(&mut self, version: NodeVersion) -> Result<()> { diff --git a/src/repository/mod.rs b/src/repository/mod.rs index d5f5f6e..b809dff 100644 --- a/src/repository/mod.rs +++ b/src/repository/mod.rs @@ -13,7 +13,7 @@ use crate::{ versioning::{SimpleVersion, VersionMetadata}, }; -use miette::{IntoDiagnostic, Result}; +use miette::{Context, IntoDiagnostic, Result}; use self::{ downloader::{versions::Versions, NodeDownloader}, @@ -175,6 +175,24 @@ impl Repository { Ok(()) } + /// Uninstalls the given node version by deleting the versions directory + #[tracing::instrument(level = "debug", skip(self))] + pub async fn uninstall(&mut self, version: &NodeVersion) -> Result<()> { + let info = self.lookup_version(version).await?; + let version_dir = NODE_VERSIONS_DIR.join(info.version.to_string()); + + if !version_dir.exists() { + return Err(VersionError::not_installed(version).into()); + } + + fs::remove_dir_all(version_dir) + .await + .into_diagnostic() + .context("Deleting node version")?; + + Ok(()) + } + /// Performs a lookup for the given node version #[tracing::instrument(level = "debug", skip(self))] pub async fn lookup_version(&mut self, version_req: &NodeVersion) -> Result<&VersionMetadata> { diff --git a/src/utils.rs b/src/utils.rs index 0081b27..2a2c789 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -3,7 +3,7 @@ use std::{ time::Duration, }; -use dialoguer::Confirm; +use dialoguer::{theme::ColorfulTheme, Confirm}; use indicatif::{ProgressBar, ProgressStyle}; pub fn progress_bar(total: u64) -> ProgressBar { @@ -32,7 +32,7 @@ pub fn progress_spinner() -> ProgressBar { } pub fn prompt(default: bool, prompt: S) -> bool { - Confirm::new() + Confirm::with_theme(&ColorfulTheme::default()) .with_prompt(prompt.to_string()) .default(default) .interact()