diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 091e41734e..5f36a4e483 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -812,7 +812,7 @@ pub async fn main( SelfSubcmd::Uninstall { no_prompt, no_modify_path, - } => self_update::uninstall(no_prompt, no_modify_path, process), + } => self_update::uninstall(no_prompt, no_modify_path, cfg), SelfSubcmd::UpgradeData => cfg.upgrade_data().map(|_| ExitCode::SUCCESS), }, RustupSubcmd::Set { subcmd } => match subcmd { diff --git a/src/cli/self_update.rs b/src/cli/self_update.rs index ef1e0a950c..59d791f5a7 100644 --- a/src/cli/self_update.rs +++ b/src/cli/self_update.rs @@ -1049,23 +1049,21 @@ async fn maybe_install_rust(opts: InstallOpts<'_>, cfg: &mut Cfg<'_>) -> Result< } /// Uninstall process: -/// 1. Remove rustup home. -/// 2. Remove all entries in `$CARGO_HOME` except `bin`. -/// 3. Remove rustup tool links and binary. -/// 4. Try to remove $CARGO_HOME/bin directory if it's empty. -/// 5. Upon successfully removing $CARGO_HOME/bin, clean up $PATH. -/// 6. Try to remove $CARGO_HOME directory if it's empty. -pub(crate) fn uninstall( - no_prompt: bool, - no_modify_path: bool, - process: &Process, -) -> Result { +/// 1. Remove all installed toolchains. +/// 2. Remove rustup home. +/// 3. Remove all entries in `$CARGO_HOME` except `bin`. +/// 4. Remove rustup tool links and binary. +/// 5. Try to remove $CARGO_HOME/bin directory if it's empty. +/// 6. Upon successfully removing $CARGO_HOME/bin, clean up $PATH. +/// 7. Try to remove $CARGO_HOME directory if it's empty. +pub(crate) fn uninstall(no_prompt: bool, no_modify_path: bool, cfg: &Cfg<'_>) -> Result { if cfg!(feature = "no-self-update") { error!("self-uninstall is disabled for this build of rustup"); error!("you should probably use your system package manager to uninstall rustup"); return Ok(ExitCode::FAILURE); } + let process = cfg.process; let cargo_home = process.cargo_home()?; if !cargo_home.join(format!("bin/rustup{EXE_SUFFIX}")).exists() { @@ -1089,6 +1087,11 @@ pub(crate) fn uninstall( } } + info!("removing toolchains"); + for toolchain in cfg.list_toolchains()? { + Toolchain::ensure_removed(cfg, toolchain.into())?; + } + info!("removing rustup home"); // Delete RUSTUP_HOME diff --git a/tests/suite/cli_self_upd.rs b/tests/suite/cli_self_upd.rs index 5794f2df33..c9778c4a54 100644 --- a/tests/suite/cli_self_upd.rs +++ b/tests/suite/cli_self_upd.rs @@ -205,6 +205,28 @@ async fn uninstall_deletes_bins() { assert!(!rust_gdbgui.exists()); } +#[tokio::test] +async fn uninstall_deletes_installed_toolchains() { + let cx = setup_empty_installed().await; + let path = cx.config.customdir.join("custom-1"); + let path = path.to_string_lossy(); + cx.config + .expect(["rustup", "toolchain", "link", "custom", &path]) + .await + .is_ok(); + cx.config + .expect(["rustup", "self", "uninstall", "-y"]) + .await + .with_stderr(snapbox::str![[r#" +... +info: uninstalling toolchain custom +info: toolchain custom uninstalled +... +"#]]) + .is_ok(); + assert!(!cx.config.rustupdir.join("toolchains").exists()); +} + #[tokio::test] async fn uninstall_works_if_some_bins_dont_exist() { let cx = setup_empty_installed().await;