From d54cdbef92b5c20dbaabeabdf543b00abe959f2f Mon Sep 17 00:00:00 2001 From: Olivier Lacroix Date: Sun, 5 May 2024 14:38:17 +1000 Subject: [PATCH 1/4] Refactor upgrade and upgrade_all --- src/cli/global/list.rs | 8 +- src/cli/global/upgrade.rs | 183 ++++++++++++++++++++-------------- src/cli/global/upgrade_all.rs | 89 +++-------------- 3 files changed, 122 insertions(+), 158 deletions(-) diff --git a/src/cli/global/list.rs b/src/cli/global/list.rs index 1a6e1684c..f690552b3 100644 --- a/src/cli/global/list.rs +++ b/src/cli/global/list.rs @@ -148,11 +148,9 @@ pub(super) async fn list_global_packages() -> miette::Result> { while let Some(entry) = dir_contents.next_entry().await.into_diagnostic()? { if entry.file_type().await.into_diagnostic()?.is_dir() { - let Ok(name) = PackageName::from_str(entry.file_name().to_string_lossy().as_ref()) - else { - continue; - }; - packages.push(name); + if let Ok(name) = PackageName::from_str(entry.file_name().to_string_lossy().as_ref()) { + packages.push(name); + } } } diff --git a/src/cli/global/upgrade.rs b/src/cli/global/upgrade.rs index 9578d350e..693e720c7 100644 --- a/src/cli/global/upgrade.rs +++ b/src/cli/global/upgrade.rs @@ -1,3 +1,4 @@ +use std::collections::{HashMap, HashSet}; use std::time::Duration; use clap::Parser; @@ -21,8 +22,9 @@ use super::list::list_global_packages; #[derive(Parser, Debug)] #[clap(arg_required_else_help = true)] pub struct Args { - /// Specifies the package that is to be upgraded. - package: String, + /// Specifies the packages to upgrade. + #[arg(required = true)] + pub specs: Vec, /// Represents the channels from which to upgrade specified package. /// Multiple channels can be specified by using this field multiple times. @@ -38,85 +40,39 @@ pub struct Args { } pub async fn execute(args: Args) -> miette::Result<()> { - // Get the MatchSpec we need to upgrade - let package_matchspec = - MatchSpec::from_str(&args.package, ParseStrictness::Strict).into_diagnostic()?; - let package_name = package_name(&package_matchspec)?; - let matchspec_has_version = package_matchspec.version.is_some(); - - // Return with error if this package is not globally installed. - if !list_global_packages() - .await? - .iter() - .any(|global_package| global_package.as_normalized() == package_name.as_normalized()) - { - miette::bail!( - "Package {} is not globally installed", - package_name.as_source() - ); - } - - let prefix_record = find_installed_package(&package_name).await?; - let installed_version = prefix_record - .repodata_record - .package_record - .version - .into_version(); - let config = Config::load_global(); - // Figure out what channels we are using - let last_installed_channel = Channel::from_str( - prefix_record.repodata_record.channel.clone(), - config.channel_config(), - ) - .into_diagnostic()?; - - let mut channels = vec![last_installed_channel]; - let input_channels = args - .channel + // Get the MatchSpec(s) we need to upgrade + let specs = args + .specs .iter() - .map(|c| Channel::from_str(c, config.channel_config())) - .collect::, _>>() - .into_diagnostic()?; - channels.extend(input_channels); - // Remove possible duplicates - channels = channels.into_iter().unique().collect::>(); - - // Fetch sparse repodata - let (authenticated_client, sparse_repodata) = - get_client_and_sparse_repodata(&channels, &config).await?; - - let records = load_package_records(package_matchspec, &sparse_repodata)?; - let package_record = records + .map(|p| MatchSpec::from_str(p, ParseStrictness::Strict).into_diagnostic()) + .collect::, _>>()?; + let names = specs .iter() - .find(|r| r.package_record.name.as_normalized() == package_name.as_normalized()) - .ok_or_else(|| { - miette::miette!( - "Package {} not found in the specified channels", - package_name.as_normalized() - ) - })?; - let toinstall_version = package_record.package_record.version.version().to_owned(); - - if !matchspec_has_version - && toinstall_version.cmp(&installed_version) != std::cmp::Ordering::Greater - { - eprintln!( - "Package {} is already up-to-date", - package_name.as_normalized(), - ); - return Ok(()); - } + .map(package_name) + .collect::, _>>()?; - upgrade_package( - &package_name, - installed_version, - toinstall_version, - records, - authenticated_client, - ) - .await + // Return with error if any package is not globally installed. + let global_packages = list_global_packages() + .await? + .into_iter() + .collect::>(); + let requested = names.iter().cloned().collect::>(); + let not_installed = requested.difference(&global_packages).collect_vec(); + match not_installed.len() { + 0 => {} // Do nothing when all packages are globally installed + 1 => miette::bail!( + "Package {} is not globally installed", + not_installed[0].as_normalized(), + ), + _ => miette::bail!( + "Packages {} are not globally installed", + not_installed.iter().map(|p| p.as_normalized()).join(", "), + ), + }; + + upgrade_packages(names, specs, config, &args.channel).await } pub(super) async fn upgrade_package( @@ -145,3 +101,78 @@ pub(super) async fn upgrade_package( pb.finish_with_message(format!("{} {}", console::style("Updated").green(), message)); Ok(()) } + +pub(super) async fn upgrade_packages( + names: Vec, + specs: Vec, + config: Config, + cli_channels: &[String], +) -> Result<(), miette::Error> { + // Get channels and versions of globally installed packages + let mut installed_versions = HashMap::with_capacity(names.len()); + let mut channels = config.compute_channels(cli_channels).into_diagnostic()?; + + for package_name in names.iter() { + let prefix_record = find_installed_package(package_name).await?; + let last_installed_channel = Channel::from_str( + prefix_record.repodata_record.channel.clone(), + config.channel_config(), + ) + .into_diagnostic()?; + + channels.push(last_installed_channel); + + let installed_version = prefix_record + .repodata_record + .package_record + .version + .into_version(); + installed_versions.insert(package_name.clone(), installed_version); + } + channels = channels.into_iter().unique().collect(); + + // Fetch sparse repodata + let (authenticated_client, sparse_repodata) = + get_client_and_sparse_repodata(&channels, &config).await?; + + // Upgrade each package when relevant + let mut upgraded = false; + for (package_name, package_matchspec) in names.into_iter().zip(specs.into_iter()) { + let matchspec_has_version = package_matchspec.version.is_some(); + let records = load_package_records(package_matchspec, &sparse_repodata)?; + let package_record = records + .iter() + .find(|r| r.package_record.name == package_name) + .ok_or_else(|| { + miette::miette!( + "Package {} not found in the specified channels", + package_name.as_normalized() + ) + })?; + let toinstall_version = package_record.package_record.version.version().to_owned(); + let installed_version = installed_versions + .get(&package_name) + .expect("should have the installed version") + .to_owned(); + + // Perform upgrade if a specific version was requested + // OR if a more recent version is available + if matchspec_has_version || toinstall_version > installed_version { + upgrade_package( + &package_name, + installed_version, + toinstall_version, + records, + authenticated_client.clone(), + ) + .await?; + upgraded = true; + } + } + + if !upgraded { + eprintln!("Nothing to upgrade"); + } + + Ok(()) +} diff --git a/src/cli/global/upgrade_all.rs b/src/cli/global/upgrade_all.rs index 358a480fd..db1406231 100644 --- a/src/cli/global/upgrade_all.rs +++ b/src/cli/global/upgrade_all.rs @@ -1,17 +1,11 @@ -use std::collections::HashMap; - use clap::Parser; use itertools::Itertools; -use miette::IntoDiagnostic; -use rattler_conda_types::{Channel, MatchSpec, ParseStrictness}; + +use rattler_conda_types::MatchSpec; use crate::config::{Config, ConfigCli}; -use super::{ - common::{find_installed_package, get_client_and_sparse_repodata, load_package_records}, - list::list_global_packages, - upgrade::upgrade_package, -}; +use super::{list::list_global_packages, upgrade::upgrade_packages}; /// Upgrade all globally installed packages #[derive(Parser, Debug)] @@ -33,75 +27,16 @@ pub struct Args { } pub async fn execute(args: Args) -> miette::Result<()> { - let packages = list_global_packages().await?; let config = Config::with_cli_config(&args.config); - let mut channels = config.compute_channels(&args.channel).into_diagnostic()?; - - let mut installed_versions = HashMap::with_capacity(packages.len()); - - for package_name in packages.iter() { - let prefix_record = find_installed_package(package_name).await?; - let last_installed_channel = Channel::from_str( - prefix_record.repodata_record.channel.clone(), - config.channel_config(), - ) - .into_diagnostic()?; - - channels.push(last_installed_channel); - - let installed_version = prefix_record - .repodata_record - .package_record - .version - .into_version(); - installed_versions.insert(package_name.as_normalized().to_owned(), installed_version); - } - - // Remove possible duplicates - channels = channels.into_iter().unique().collect::>(); - - // Fetch sparse repodata - let (authenticated_client, sparse_repodata) = - get_client_and_sparse_repodata(&channels, &config).await?; - - let mut upgraded = false; - for package_name in packages.iter() { - let package_matchspec = - MatchSpec::from_str(package_name.as_source(), ParseStrictness::Strict) - .into_diagnostic()?; - let records = load_package_records(package_matchspec, &sparse_repodata)?; - let package_record = records - .iter() - .find(|r| r.package_record.name.as_normalized() == package_name.as_normalized()) - .ok_or_else(|| { - miette::miette!( - "Package {} not found in the specified channels", - package_name.as_normalized() - ) - })?; - let toinstall_version = package_record.package_record.version.version().to_owned(); - let installed_version = installed_versions - .get(package_name.as_normalized()) - .expect("should have the installed version") - .to_owned(); - - // Prvent downgrades - if toinstall_version.cmp(&installed_version) == std::cmp::Ordering::Greater { - upgrade_package( - package_name, - installed_version, - toinstall_version, - records, - authenticated_client.clone(), - ) - .await?; - upgraded = true; - } - } - if !upgraded { - eprintln!("Nothing to upgrade"); - } + let names = list_global_packages().await?; + let specs = names + .iter() + .map(|name| MatchSpec { + name: Some(name.clone()), + ..Default::default() + }) + .collect_vec(); - Ok(()) + upgrade_packages(names, specs, config, &args.channel).await } From 17b5407a143fb0e74f9bcbc373eff2496e467b6d Mon Sep 17 00:00:00 2001 From: Olivier Lacroix Date: Sun, 5 May 2024 15:42:53 +1000 Subject: [PATCH 2/4] refactor parsing of packages arguments --- src/cli/global/common.rs | 19 ++++++++++++++++++- src/cli/global/install.rs | 23 +++++++++-------------- src/cli/global/remove.rs | 29 +++++++++-------------------- src/cli/global/upgrade.rs | 35 ++++++++++++++++------------------- src/cli/global/upgrade_all.rs | 23 +++++++++++++---------- 5 files changed, 65 insertions(+), 64 deletions(-) diff --git a/src/cli/global/common.rs b/src/cli/global/common.rs index 01dc006f9..ddbe0aaac 100644 --- a/src/cli/global/common.rs +++ b/src/cli/global/common.rs @@ -3,7 +3,8 @@ use std::path::PathBuf; use indexmap::IndexMap; use miette::IntoDiagnostic; use rattler_conda_types::{ - Channel, ChannelConfig, MatchSpec, PackageName, Platform, PrefixRecord, RepoDataRecord, + Channel, ChannelConfig, MatchSpec, PackageName, ParseStrictness, Platform, PrefixRecord, + RepoDataRecord, }; use rattler_repodata_gateway::sparse::SparseRepoData; use rattler_solve::{resolvo, ChannelPriority, SolverImpl, SolverTask}; @@ -16,6 +17,22 @@ use crate::{ utils::reqwest::build_reqwest_clients, }; +/// A trait to facilitate extraction of packages data from arguments +pub(super) trait HasSpecs { + /// returns packages passed as arguments to the command + fn packages(&self) -> Vec<&str>; + + fn specs(&self) -> miette::Result> { + let mut map = IndexMap::with_capacity(self.packages().len()); + for package in self.packages() { + let spec = MatchSpec::from_str(package, ParseStrictness::Strict).into_diagnostic()?; + let name = package_name(&spec)?; + map.insert(name, spec); + } + + Ok(map) + } +} /// Global binaries directory, default to `$HOME/.pixi/bin` pub struct BinDir(pub PathBuf); diff --git a/src/cli/global/install.rs b/src/cli/global/install.rs index 77019b267..00eb343ce 100644 --- a/src/cli/global/install.rs +++ b/src/cli/global/install.rs @@ -10,9 +10,7 @@ use itertools::Itertools; use miette::IntoDiagnostic; use rattler::install::Transaction; use rattler::package_cache::PackageCache; -use rattler_conda_types::{ - MatchSpec, PackageName, ParseStrictness, Platform, PrefixRecord, RepoDataRecord, -}; +use rattler_conda_types::{PackageName, Platform, PrefixRecord, RepoDataRecord}; use rattler_shell::{ activation::{ActivationVariables, Activator, PathModificationBehavior}, shell::Shell, @@ -22,7 +20,7 @@ use reqwest_middleware::ClientWithMiddleware; use super::common::{ channel_name_from_prefix, find_designated_package, get_client_and_sparse_repodata, - load_package_records, package_name, BinDir, BinEnvDir, + load_package_records, BinDir, BinEnvDir, HasSpecs, }; /// Installs the defined package in a global accessible location. @@ -48,6 +46,12 @@ pub struct Args { config: ConfigCli, } +impl HasSpecs for Args { + fn packages(&self) -> Vec<&str> { + self.package.iter().map(AsRef::as_ref).collect() + } +} + /// Create the environment activation script fn create_activation_script(prefix: &Prefix, shell: ShellEnum) -> miette::Result { let activator = @@ -244,22 +248,13 @@ pub async fn execute(args: Args) -> miette::Result<()> { let config = Config::with_cli_config(&args.config); let channels = config.compute_channels(&args.channel).into_diagnostic()?; - // Find the MatchSpec we want to install - let specs = args - .package - .into_iter() - .map(|package_str| MatchSpec::from_str(&package_str, ParseStrictness::Strict)) - .collect::, _>>() - .into_diagnostic()?; - // Fetch sparse repodata let (authenticated_client, sparse_repodata) = get_client_and_sparse_repodata(&channels, &config).await?; // Install the package(s) let mut executables = vec![]; - for package_matchspec in specs { - let package_name = package_name(&package_matchspec)?; + for (package_name, package_matchspec) in args.specs()? { let records = load_package_records(package_matchspec, &sparse_repodata)?; let (prefix_package, scripts, _) = diff --git a/src/cli/global/remove.rs b/src/cli/global/remove.rs index 122095a4b..c1085b347 100644 --- a/src/cli/global/remove.rs +++ b/src/cli/global/remove.rs @@ -4,12 +4,11 @@ use clap::Parser; use clap_verbosity_flag::{Level, Verbosity}; use itertools::Itertools; use miette::IntoDiagnostic; -use rattler_conda_types::ParseStrictness::Strict; -use rattler_conda_types::{MatchSpec, PackageName}; +use rattler_conda_types::PackageName; use crate::prefix::Prefix; -use super::common::{find_designated_package, BinDir, BinEnvDir}; +use super::common::{find_designated_package, BinDir, BinEnvDir, HasSpecs}; use super::install::{find_and_map_executable_scripts, BinScriptMapping}; /// Removes a package previously installed into a globally accessible location via `pixi global install`. @@ -24,24 +23,14 @@ pub struct Args { verbose: Verbosity, } +impl HasSpecs for Args { + fn packages(&self) -> Vec<&str> { + self.package.iter().map(AsRef::as_ref).collect() + } +} + pub async fn execute(args: Args) -> miette::Result<()> { - // Find the MatchSpec we want to remove - let specs = args - .package - .into_iter() - .map(|package_str| MatchSpec::from_str(&package_str, Strict)) - .collect::, _>>() - .into_diagnostic()?; - let packages = specs - .into_iter() - .map(|spec| { - spec.name - .clone() - .ok_or_else(|| miette::miette!("could not find package name in MatchSpec {}", spec)) - }) - .collect::, _>>()?; - - for package_name in packages { + for (package_name, _) in args.specs()? { remove_global_package(package_name, &args.verbose).await?; } diff --git a/src/cli/global/upgrade.rs b/src/cli/global/upgrade.rs index 693e720c7..388f14a65 100644 --- a/src/cli/global/upgrade.rs +++ b/src/cli/global/upgrade.rs @@ -2,18 +2,18 @@ use std::collections::{HashMap, HashSet}; use std::time::Duration; use clap::Parser; +use indexmap::IndexMap; use indicatif::ProgressBar; use itertools::Itertools; use miette::IntoDiagnostic; -use rattler_conda_types::{Channel, MatchSpec, PackageName, Version}; -use rattler_conda_types::{ParseStrictness, RepoDataRecord}; +use rattler_conda_types::{Channel, MatchSpec, PackageName, RepoDataRecord, Version}; use reqwest_middleware::ClientWithMiddleware; use crate::config::Config; use crate::progress::{global_multi_progress, long_running_progress_style}; use super::common::{ - find_installed_package, get_client_and_sparse_repodata, load_package_records, package_name, + find_installed_package, get_client_and_sparse_repodata, load_package_records, HasSpecs, }; use super::install::globally_install_package; use super::list::list_global_packages; @@ -39,26 +39,24 @@ pub struct Args { channel: Vec, } +impl HasSpecs for Args { + fn packages(&self) -> Vec<&str> { + self.specs.iter().map(AsRef::as_ref).collect() + } +} + pub async fn execute(args: Args) -> miette::Result<()> { let config = Config::load_global(); // Get the MatchSpec(s) we need to upgrade - let specs = args - .specs - .iter() - .map(|p| MatchSpec::from_str(p, ParseStrictness::Strict).into_diagnostic()) - .collect::, _>>()?; - let names = specs - .iter() - .map(package_name) - .collect::, _>>()?; + let specs = args.specs()?; // Return with error if any package is not globally installed. let global_packages = list_global_packages() .await? .into_iter() .collect::>(); - let requested = names.iter().cloned().collect::>(); + let requested = specs.keys().cloned().collect::>(); let not_installed = requested.difference(&global_packages).collect_vec(); match not_installed.len() { 0 => {} // Do nothing when all packages are globally installed @@ -72,7 +70,7 @@ pub async fn execute(args: Args) -> miette::Result<()> { ), }; - upgrade_packages(names, specs, config, &args.channel).await + upgrade_packages(specs, config, &args.channel).await } pub(super) async fn upgrade_package( @@ -103,16 +101,15 @@ pub(super) async fn upgrade_package( } pub(super) async fn upgrade_packages( - names: Vec, - specs: Vec, + specs: IndexMap, config: Config, cli_channels: &[String], ) -> Result<(), miette::Error> { // Get channels and versions of globally installed packages - let mut installed_versions = HashMap::with_capacity(names.len()); + let mut installed_versions = HashMap::with_capacity(specs.len()); let mut channels = config.compute_channels(cli_channels).into_diagnostic()?; - for package_name in names.iter() { + for package_name in specs.keys() { let prefix_record = find_installed_package(package_name).await?; let last_installed_channel = Channel::from_str( prefix_record.repodata_record.channel.clone(), @@ -137,7 +134,7 @@ pub(super) async fn upgrade_packages( // Upgrade each package when relevant let mut upgraded = false; - for (package_name, package_matchspec) in names.into_iter().zip(specs.into_iter()) { + for (package_name, package_matchspec) in specs { let matchspec_has_version = package_matchspec.version.is_some(); let records = load_package_records(package_matchspec, &sparse_repodata)?; let package_record = records diff --git a/src/cli/global/upgrade_all.rs b/src/cli/global/upgrade_all.rs index db1406231..c46ebb0fb 100644 --- a/src/cli/global/upgrade_all.rs +++ b/src/cli/global/upgrade_all.rs @@ -1,5 +1,5 @@ use clap::Parser; -use itertools::Itertools; +use indexmap::IndexMap; use rattler_conda_types::MatchSpec; @@ -30,13 +30,16 @@ pub async fn execute(args: Args) -> miette::Result<()> { let config = Config::with_cli_config(&args.config); let names = list_global_packages().await?; - let specs = names - .iter() - .map(|name| MatchSpec { - name: Some(name.clone()), - ..Default::default() - }) - .collect_vec(); - - upgrade_packages(names, specs, config, &args.channel).await + let mut specs = IndexMap::with_capacity(names.len()); + for name in names { + specs.insert( + name.clone(), + MatchSpec { + name: Some(name), + ..Default::default() + }, + ); + } + + upgrade_packages(specs, config, &args.channel).await } From 3f081097ff7b6155231e1b707531b55eec32704c Mon Sep 17 00:00:00 2001 From: Olivier Lacroix Date: Sun, 5 May 2024 16:09:03 +1000 Subject: [PATCH 3/4] Let `find_installed_package` report any non globally installed package --- src/cli/global/common.rs | 2 +- src/cli/global/upgrade.rs | 25 +------------------------ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/cli/global/common.rs b/src/cli/global/common.rs index ddbe0aaac..3e3777ef9 100644 --- a/src/cli/global/common.rs +++ b/src/cli/global/common.rs @@ -125,7 +125,7 @@ pub fn bin_env_dir() -> Option { /// # Returns /// /// The package name from the given MatchSpec -pub(super) fn package_name(package_matchspec: &MatchSpec) -> miette::Result { +fn package_name(package_matchspec: &MatchSpec) -> miette::Result { package_matchspec.name.clone().ok_or_else(|| { miette::miette!( "could not find package name in MatchSpec {}", diff --git a/src/cli/global/upgrade.rs b/src/cli/global/upgrade.rs index 388f14a65..fa512395b 100644 --- a/src/cli/global/upgrade.rs +++ b/src/cli/global/upgrade.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::time::Duration; use clap::Parser; @@ -16,7 +16,6 @@ use super::common::{ find_installed_package, get_client_and_sparse_repodata, load_package_records, HasSpecs, }; use super::install::globally_install_package; -use super::list::list_global_packages; /// Upgrade specific package which is installed globally. #[derive(Parser, Debug)] @@ -47,29 +46,7 @@ impl HasSpecs for Args { pub async fn execute(args: Args) -> miette::Result<()> { let config = Config::load_global(); - - // Get the MatchSpec(s) we need to upgrade let specs = args.specs()?; - - // Return with error if any package is not globally installed. - let global_packages = list_global_packages() - .await? - .into_iter() - .collect::>(); - let requested = specs.keys().cloned().collect::>(); - let not_installed = requested.difference(&global_packages).collect_vec(); - match not_installed.len() { - 0 => {} // Do nothing when all packages are globally installed - 1 => miette::bail!( - "Package {} is not globally installed", - not_installed[0].as_normalized(), - ), - _ => miette::bail!( - "Packages {} are not globally installed", - not_installed.iter().map(|p| p.as_normalized()).join(", "), - ), - }; - upgrade_packages(specs, config, &args.channel).await } From 5888f1c105b85b4e311676d7c693ff6d549826dd Mon Sep 17 00:00:00 2001 From: Olivier Lacroix Date: Sun, 5 May 2024 16:43:36 +1000 Subject: [PATCH 4/4] Inline single use function --- src/cli/global/upgrade.rs | 55 +++++++++++++-------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/src/cli/global/upgrade.rs b/src/cli/global/upgrade.rs index fa512395b..d10967b31 100644 --- a/src/cli/global/upgrade.rs +++ b/src/cli/global/upgrade.rs @@ -6,8 +6,7 @@ use indexmap::IndexMap; use indicatif::ProgressBar; use itertools::Itertools; use miette::IntoDiagnostic; -use rattler_conda_types::{Channel, MatchSpec, PackageName, RepoDataRecord, Version}; -use reqwest_middleware::ClientWithMiddleware; +use rattler_conda_types::{Channel, MatchSpec, PackageName}; use crate::config::Config; use crate::progress::{global_multi_progress, long_running_progress_style}; @@ -50,38 +49,11 @@ pub async fn execute(args: Args) -> miette::Result<()> { upgrade_packages(specs, config, &args.channel).await } -pub(super) async fn upgrade_package( - package_name: &PackageName, - installed_version: Version, - toinstall_version: Version, - records: Vec, - authenticated_client: ClientWithMiddleware, -) -> miette::Result<()> { - let message = format!( - "{} v{} -> v{}", - package_name.as_normalized(), - installed_version, - toinstall_version - ); - - let pb = global_multi_progress().add(ProgressBar::new_spinner()); - pb.enable_steady_tick(Duration::from_millis(100)); - pb.set_style(long_running_progress_style()); - pb.set_message(format!( - "{} {}", - console::style("Updating").green(), - message - )); - globally_install_package(package_name, records, authenticated_client).await?; - pb.finish_with_message(format!("{} {}", console::style("Updated").green(), message)); - Ok(()) -} - pub(super) async fn upgrade_packages( specs: IndexMap, config: Config, cli_channels: &[String], -) -> Result<(), miette::Error> { +) -> miette::Result<()> { // Get channels and versions of globally installed packages let mut installed_versions = HashMap::with_capacity(specs.len()); let mut channels = config.compute_channels(cli_channels).into_diagnostic()?; @@ -132,14 +104,23 @@ pub(super) async fn upgrade_packages( // Perform upgrade if a specific version was requested // OR if a more recent version is available if matchspec_has_version || toinstall_version > installed_version { - upgrade_package( - &package_name, + let message = format!( + "{} v{} -> v{}", + package_name.as_normalized(), installed_version, - toinstall_version, - records, - authenticated_client.clone(), - ) - .await?; + toinstall_version + ); + + let pb = global_multi_progress().add(ProgressBar::new_spinner()); + pb.enable_steady_tick(Duration::from_millis(100)); + pb.set_style(long_running_progress_style()); + pb.set_message(format!( + "{} {}", + console::style("Updating").green(), + message + )); + globally_install_package(&package_name, records, authenticated_client.clone()).await?; + pb.finish_with_message(format!("{} {}", console::style("Updated").green(), message)); upgraded = true; } }