diff --git a/crates/volta-core/src/tool/mod.rs b/crates/volta-core/src/tool/mod.rs index 83c2bdaa3..fe8dda012 100644 --- a/crates/volta-core/src/tool/mod.rs +++ b/crates/volta-core/src/tool/mod.rs @@ -67,6 +67,8 @@ pub trait Tool: Display { fn install(self: Box, session: &mut Session) -> Fallible<()>; /// Pin a tool in the local project so that it is usable within the project fn pin(self: Box, session: &mut Session) -> Fallible<()>; + /// Uninstall a tool + fn uninstall(self: Box, session: &mut Session) -> Fallible<()>; } /// Specification for a tool and its associated version. diff --git a/crates/volta-core/src/tool/node/mod.rs b/crates/volta-core/src/tool/node/mod.rs index efaf768ef..caa419527 100644 --- a/crates/volta-core/src/tool/node/mod.rs +++ b/crates/volta-core/src/tool/node/mod.rs @@ -5,12 +5,14 @@ use super::{ info_project_version, FetchStatus, Tool, }; use crate::error::{ErrorKind, Fallible}; +use crate::fs::remove_dir_if_exists; use crate::inventory::node_available; +use crate::layout::volta_home; use crate::session::Session; -use crate::style::{note_prefix, tool_version}; +use crate::style::{note_prefix, success_prefix, tool_version}; use crate::sync::VoltaLock; use cfg_if::cfg_if; -use log::info; +use log::{info, warn}; use node_semver::Version; mod fetch; @@ -244,6 +246,21 @@ impl Tool for Node { Err(ErrorKind::NotInPackage.into()) } } + fn uninstall(self: Box, _session: &mut Session) -> Fallible<()> { + let home = volta_home()?; + // Acquire a lock on the Volta directory, if possible, to prevent concurrent changes + let _lock: Result = VoltaLock::acquire(); + + let node_dir = home.node_image_root_dir().join(self.version.to_string()); + if node_dir.exists() { + remove_dir_if_exists(&node_dir)?; + info!("{} 'node@{}' uninstalled", success_prefix(), self.version); + } else { + warn!("No version 'node@{}' found to uninstall", self.version); + } + + Ok(()) + } } impl Display for Node { diff --git a/crates/volta-core/src/tool/npm/mod.rs b/crates/volta-core/src/tool/npm/mod.rs index 945e0f5d7..07b737994 100644 --- a/crates/volta-core/src/tool/npm/mod.rs +++ b/crates/volta-core/src/tool/npm/mod.rs @@ -86,6 +86,12 @@ impl Tool for Npm { Err(ErrorKind::NotInPackage.into()) } } + fn uninstall(self: Box, _session: &mut Session) -> Fallible<()> { + Err(ErrorKind::Unimplemented { + feature: "Uninstalling npm".into(), + } + .into()) + } } impl Display for Npm { @@ -168,6 +174,13 @@ impl Tool for BundledNpm { None => Err(ErrorKind::NotInPackage.into()), } } + + fn uninstall(self: Box, _session: &mut Session) -> Fallible<()> { + Err(ErrorKind::Unimplemented { + feature: "Uninstalling bundled npm".into(), + } + .into()) + } } impl Display for BundledNpm { diff --git a/crates/volta-core/src/tool/package/mod.rs b/crates/volta-core/src/tool/package/mod.rs index c8ae39fc5..6e2592861 100644 --- a/crates/volta-core/src/tool/package/mod.rs +++ b/crates/volta-core/src/tool/package/mod.rs @@ -108,6 +108,10 @@ impl Tool for Package { fn pin(self: Box, _session: &mut Session) -> Fallible<()> { Err(ErrorKind::CannotPinPackage { package: self.name }.into()) } + + fn uninstall(self: Box, _session: &mut Session) -> Fallible<()> { + uninstall(&self.name) + } } impl Display for Package { diff --git a/crates/volta-core/src/tool/pnpm/mod.rs b/crates/volta-core/src/tool/pnpm/mod.rs index 7c2751877..996305bca 100644 --- a/crates/volta-core/src/tool/pnpm/mod.rs +++ b/crates/volta-core/src/tool/pnpm/mod.rs @@ -1,4 +1,5 @@ use node_semver::Version; +use std::env; use std::fmt::{self, Display}; use crate::error::{ErrorKind, Fallible}; @@ -6,6 +7,7 @@ use crate::inventory::pnpm_available; use crate::session::Session; use crate::style::tool_version; use crate::sync::VoltaLock; +use crate::VOLTA_FEATURE_PNPM; use super::{ check_fetched, debug_already_fetched, info_fetched, info_installed, info_pinned, @@ -15,6 +17,7 @@ use super::{ mod fetch; mod resolve; +use super::package::uninstall; pub use resolve::resolve; /// The Tool implementation for fetching and installing pnpm @@ -87,6 +90,17 @@ impl Tool for Pnpm { Err(ErrorKind::NotInPackage.into()) } } + + fn uninstall(self: Box, _session: &mut Session) -> Fallible<()> { + if env::var_os(VOLTA_FEATURE_PNPM).is_some() { + Err(ErrorKind::Unimplemented { + feature: "Uninstalling pnpm".into(), + } + .into()) + } else { + uninstall("pnpm") + } + } } impl Display for Pnpm { diff --git a/crates/volta-core/src/tool/yarn/mod.rs b/crates/volta-core/src/tool/yarn/mod.rs index a252317d0..17d66a098 100644 --- a/crates/volta-core/src/tool/yarn/mod.rs +++ b/crates/volta-core/src/tool/yarn/mod.rs @@ -85,6 +85,12 @@ impl Tool for Yarn { Err(ErrorKind::NotInPackage.into()) } } + fn uninstall(self: Box, _session: &mut Session) -> Fallible<()> { + Err(ErrorKind::Unimplemented { + feature: "Uninstalling yarn".into(), + } + .into()) + } } impl Display for Yarn { diff --git a/src/command/uninstall.rs b/src/command/uninstall.rs index 9137fc2bc..4446d7db0 100644 --- a/src/command/uninstall.rs +++ b/src/command/uninstall.rs @@ -1,7 +1,6 @@ use volta_core::error::{ExitCode, Fallible}; use volta_core::session::{ActivityKind, Session}; use volta_core::tool; -use volta_core::version::VersionSpec; use crate::command::Command; @@ -15,10 +14,8 @@ impl Command for Uninstall { fn run(self, session: &mut Session) -> Fallible { session.add_event_start(ActivityKind::Uninstall); - let version = VersionSpec::default(); - let tool = tool::Spec::from_str_and_version(&self.tool, version); - - tool.uninstall()?; + let tool = tool::Spec::try_from_str(&self.tool)?; + tool.resolve(session)?.uninstall(session)?; session.add_event_end(ActivityKind::Uninstall, ExitCode::Success); Ok(ExitCode::Success)