diff --git a/src/install.rs b/src/install.rs index 20964cfba4..784b27d409 100644 --- a/src/install.rs +++ b/src/install.rs @@ -1,6 +1,6 @@ //! Installation and upgrade of both distribution-managed and local //! toolchains -use std::path::{Path, PathBuf}; +use std::path::Path; use tracing::debug; @@ -8,7 +8,7 @@ use crate::{ config::Cfg, dist::{DistOptions, manifest::ManifestWithHash, prefix::InstallPrefix}, errors::RustupError, - toolchain::{CustomToolchainName, LocalToolchainName, Toolchain}, + toolchain::{CustomToolchainName, Toolchain}, utils, }; @@ -35,98 +35,77 @@ impl InstallMethod<'_, '_> { self, manifest: Option, ) -> anyhow::Result { + let cfg = match self { + Self::Link { cfg, .. } | Self::Dist(DistOptions { cfg, .. }) => cfg, + }; + // Initialize rayon for use by the remove_dir_all crate limiting the number of threads. // This will error if rayon is already initialized but it's fine to ignore that. let _ = rayon::ThreadPoolBuilder::new() - .num_threads(self.cfg().process.io_thread_count()?.into()) + .num_threads(cfg.process.io_thread_count()?.into()) .build_global(); - let local_name = self.local_name(); - match &self { - InstallMethod::Link { .. } - | InstallMethod::Dist(DistOptions { - old_date_version: None, - .. - }) => debug!("installing toolchain {local_name}",), - _ => debug!("updating existing install for '{local_name}'"), - } - debug!("toolchain directory: {}", self.dest_path().display()); - let updated = self.run(&self.dest_path(), manifest).await?; - - let status = match updated { - false => { - debug!("toolchain is already up to date"); - UpdateStatus::Unchanged + let local_name = match &self { + Self::Link { dest, .. } => { + let name = (*dest).clone().into(); + debug!("linking toolchain {name}"); + name } - true => { - debug!("toolchain {local_name} installed"); - match &self { - InstallMethod::Dist(DistOptions { - old_date_version: Some((_, v)), - .. - }) => UpdateStatus::Updated(v.clone()), - InstallMethod::Link { .. } | InstallMethod::Dist { .. } => { - UpdateStatus::Installed - } + Self::Dist(DistOptions { + toolchain: desc, + old_date_version, + .. + }) => { + let name = (*desc).clone().into(); + if old_date_version.is_some() { + debug!("updating existing install for '{name}'"); + } else { + debug!("installing toolchain {name}"); } + name } }; - // Final check, to ensure we're installed - match Toolchain::exists(self.cfg(), &local_name)? { - true => Ok(status), - false => Err(RustupError::ToolchainNotInstallable(local_name.to_string()).into()), - } - } - - async fn run(&self, path: &Path, manifest: Option) -> anyhow::Result { - if path.exists() { - // Don't uninstall first for Dist method - match self { - InstallMethod::Dist { .. } => {} - _ => { - uninstall(path)?; - } - } + let dest_path = &cfg.toolchain_path(&local_name); + debug!("toolchain directory: {}", dest_path.display()); + if dest_path.exists() && !matches!(self, Self::Dist { .. }) { + uninstall(dest_path)?; } - match self { - InstallMethod::Link { src, .. } => { - utils::symlink_dir(src, path)?; - Ok(true) + let status = match &self { + Self::Link { src, .. } => { + utils::symlink_dir(src, dest_path)?; + UpdateStatus::Installed } - InstallMethod::Dist(opts) => { - let prefix = &InstallPrefix::from(path.to_owned()); - let maybe_new_hash = opts.install_into(prefix, manifest).await?; - - if let Some(hash) = maybe_new_hash { + Self::Dist(opts) => match opts + .install_into(&InstallPrefix::from(dest_path.clone()), manifest) + .await? + { + None => UpdateStatus::Unchanged, + Some(hash) => { utils::write_file("update hash", &opts.update_hash, &hash)?; - Ok(true) - } else { - Ok(false) + match opts { + DistOptions { + old_date_version: Some((_, v)), + .. + } => UpdateStatus::Updated(v.clone()), + _ => UpdateStatus::Installed, + } } - } - } - } + }, + }; - fn cfg(&self) -> &Cfg<'_> { - match self { - InstallMethod::Link { cfg, .. } => cfg, - InstallMethod::Dist(DistOptions { cfg, .. }) => cfg, + // Final check, to ensure we're installed + if !Toolchain::exists(cfg, &local_name)? { + return Err(RustupError::ToolchainNotInstallable(local_name.to_string()).into()); } - } - fn local_name(&self) -> LocalToolchainName { - match self { - InstallMethod::Link { dest, .. } => (*dest).clone().into(), - InstallMethod::Dist(DistOptions { - toolchain: desc, .. - }) => (*desc).clone().into(), - } - } + match &status { + UpdateStatus::Unchanged => debug!("toolchain is already up to date"), + _ => debug!("toolchain {local_name} installed"), + }; - fn dest_path(&self) -> PathBuf { - self.cfg().toolchain_path(&self.local_name()) + Ok(status) } }