diff --git a/crates/pm/src/service/install.rs b/crates/pm/src/service/install.rs index 0390a17af1..bdae40e841 100644 --- a/crates/pm/src/service/install.rs +++ b/crates/pm/src/service/install.rs @@ -21,7 +21,8 @@ use crate::util::downloader::download_stats; use crate::util::json::load_package_lock_json_from_path; use crate::util::linker::link; use crate::util::logger::{ - PROGRESS_BAR, finish_progress_bar, log_progress, print_install_counts, start_progress_bar, + finish_progress_bar, log_progress, print_install_counts, progress_inc, progress_set_length, + start_progress_bar, }; use utoo_ruborist::compat::{is_cpu_compatible, is_os_compatible}; @@ -89,7 +90,7 @@ pub async fn install_packages( for (path, package) in packages.iter() { // Skip packages based on omit config if should_omit_package(package, omit) { - PROGRESS_BAR.inc(1); + progress_inc(1); continue; } let path = path.clone(); @@ -108,13 +109,13 @@ pub async fn install_packages( if package.link.is_some() { let link_name = extract_package_name(&path); if link_name.is_empty() { - PROGRESS_BAR.inc(1); + progress_inc(1); continue; } link(Path::new(&resolved), Path::new(&path)) .await .with_context(|| format!("Link failed: {resolved} -> {path}"))?; - PROGRESS_BAR.inc(1); + progress_inc(1); continue; } @@ -122,14 +123,14 @@ pub async fn install_packages( if let Some(ref cpu) = package.cpu && !is_cpu_compatible(cpu) { - PROGRESS_BAR.inc(1); + progress_inc(1); continue; } if let Some(ref os) = package.os && !is_os_compatible(os) { - PROGRESS_BAR.inc(1); + progress_inc(1); continue; } @@ -153,18 +154,18 @@ pub async fn install_packages( tracing::warn!( "Optional dependency {name} failed (ignored): {e:#}" ); - PROGRESS_BAR.inc(1); + progress_inc(1); return Ok(()); } return Err(e); } - PROGRESS_BAR.inc(1); + progress_inc(1); log_progress(&format!("{name} resolved")); update_package_binary(&target_path, &name).await }); clone_tasks.push(task); } else { - PROGRESS_BAR.inc(1); + progress_inc(1); } } } @@ -260,7 +261,7 @@ impl InstallService { if !package_lock.packages.is_empty() { start_progress_bar(); - PROGRESS_BAR.set_length(package_lock.packages.len() as u64); + progress_set_length(package_lock.packages.len() as u64); } let link_start = Instant::now(); diff --git a/crates/pm/src/util/logger.rs b/crates/pm/src/util/logger.rs index 6ba124bb24..c8570b2eca 100644 --- a/crates/pm/src/util/logger.rs +++ b/crates/pm/src/util/logger.rs @@ -161,6 +161,27 @@ pub fn log_progress(text: &str) { PROGRESS_BAR.set_message(text.to_string()); } +/// TTY-gated `PROGRESS_BAR.inc(1)`. Non-TTY callers pay no Mutex cost — +/// indicatif's `inc` always takes the internal `Mutex` +/// write-lock even with a hidden draw target, which contends across the +/// install loop's spawned tasks. +#[inline] +pub fn progress_inc(n: u64) { + if !*IS_TTY { + return; + } + PROGRESS_BAR.inc(n); +} + +/// TTY-gated `PROGRESS_BAR.set_length`. Same rationale as [`progress_inc`]. +#[inline] +pub fn progress_set_length(len: u64) { + if !*IS_TTY { + return; + } + PROGRESS_BAR.set_length(len); +} + // Global timer for log_time/log_time_end static START_TIME: OnceCell = OnceCell::new();