From 5ebff2c84f0a5235ad4b7e20452598752a82a12d Mon Sep 17 00:00:00 2001 From: Cloud0310 <60375730+Cloud0310@users.noreply.github.com> Date: Thu, 26 Mar 2026 04:21:08 +0800 Subject: [PATCH 1/2] refactor: extracted `progress_style` method for DownloadStatus --- src/dist/download.rs | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/dist/download.rs b/src/dist/download.rs index a662483ac6..d188bf6337 100644 --- a/src/dist/download.rs +++ b/src/dist/download.rs @@ -285,16 +285,18 @@ impl<'a> DownloadCfg<'a> { Ok(Some((file, partial_hash))) } - pub(crate) fn status_for(&self, component: impl Into>) -> DownloadStatus { + pub(crate) fn status_for( + &self, + component_name: impl Into>, + ) -> DownloadStatus { let progress = ProgressBar::hidden(); progress.set_style( - ProgressStyle::with_template( - "{msg:>13.bold} downloading [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", + DownloadStatus::progress_style( + "downloading [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", ) - .unwrap() .progress_chars("## "), ); - progress.set_message(component); + progress.set_message(component_name); self.tracker.multi_progress_bars.add(progress.clone()); DownloadStatus { @@ -360,43 +362,39 @@ impl DownloadStatus { *retry_time = None; self.progress.set_style( - ProgressStyle::with_template( - "{msg:>13.bold} downloading [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", + DownloadStatus::progress_style( + "downloading [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", ) - .unwrap() .progress_chars("## "), ); } pub(crate) fn finished(&self) { - self.progress.set_style( - ProgressStyle::with_template("{msg:>13.bold} pending installation {total_bytes:>20}") - .unwrap(), - ); + self.progress.set_style(DownloadStatus::progress_style( + "pending installation {total_bytes:>20}", + )); self.progress.tick(); // A tick is needed for the new style to appear, as it is static. } pub(crate) fn failed(&self) { - self.progress.set_style( - ProgressStyle::with_template("{msg:>13.bold} download failed after {elapsed}").unwrap(), - ); + self.progress.set_style(DownloadStatus::progress_style( + "download failed after {elapsed}", + )); self.progress.finish(); } pub(crate) fn retrying(&self) { *self.retry_time.lock().unwrap() = Some(Instant::now()); - self.progress.set_style( - ProgressStyle::with_template("{msg:>13.bold} retrying download...").unwrap(), - ); + self.progress + .set_style(DownloadStatus::progress_style("retrying download...")); } pub(crate) fn unpack(&self, inner: T) -> ProgressBarIter { self.progress.reset(); self.progress.set_style( - ProgressStyle::with_template( - "{msg:>13.bold} unpacking [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", + DownloadStatus::progress_style( + "unpacking [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", ) - .unwrap() .progress_chars("## "), ); self.progress.wrap_read(inner) @@ -404,21 +402,23 @@ impl DownloadStatus { pub(crate) fn installing(&self) { self.progress.set_style( - ProgressStyle::with_template( - "{msg:>13.bold} installing {spinner:.green} {total_bytes:>28}", - ) - .unwrap() - .tick_chars(r"|/-\ "), + DownloadStatus::progress_style("installing {spinner:.green} {total_bytes:>28}") + .tick_chars(r"|/-\ "), ); self.progress.enable_steady_tick(Duration::from_millis(100)); } pub(crate) fn installed(&self) { - self.progress.set_style( - ProgressStyle::with_template("{msg:>13.bold} installed {total_bytes:>31}").unwrap(), - ); + self.progress.set_style(DownloadStatus::progress_style( + "installed {total_bytes:>31}", + )); self.progress.finish(); } + + fn progress_style(suffix: &str) -> ProgressStyle { + let template = format!("{{msg:>13.bold}} {suffix}"); + ProgressStyle::with_template(&template).unwrap() + } } fn file_hash(path: &Path) -> Result { From 8e9d8e845f726feefb53218ca4628a6ffd65f95e Mon Sep 17 00:00:00 2001 From: Cloud0310 <60375730+Cloud0310@users.noreply.github.com> Date: Sat, 28 Mar 2026 20:56:13 +0800 Subject: [PATCH 2/2] fix: install message misalignment. Use dynamic name_width for progress templates so component status texts are correctly aligned. Pass computed max_name_width from manifestation into DownloadCfg/ComponentBinary and update progress_style and callers accordingly. --- src/dist/download.rs | 27 +++++++++++++++++++++------ src/dist/manifestation.rs | 21 ++++++++++++++++++--- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/dist/download.rs b/src/dist/download.rs index d188bf6337..74c5aa3249 100644 --- a/src/dist/download.rs +++ b/src/dist/download.rs @@ -288,10 +288,12 @@ impl<'a> DownloadCfg<'a> { pub(crate) fn status_for( &self, component_name: impl Into>, + name_width: usize, ) -> DownloadStatus { let progress = ProgressBar::hidden(); progress.set_style( DownloadStatus::progress_style( + name_width, "downloading [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", ) .progress_chars("## "), @@ -302,6 +304,7 @@ impl<'a> DownloadCfg<'a> { DownloadStatus { progress, retry_time: Mutex::new(None), + name_width, } } @@ -345,6 +348,8 @@ pub(crate) struct DownloadStatus { /// bar would reappear immediately, not allowing the user to correctly see the message, /// before the progress bar starts again. retry_time: Mutex>, + /// The dynamic maximum width of the component names for alignment + name_width: usize, } impl DownloadStatus { @@ -363,6 +368,7 @@ impl DownloadStatus { *retry_time = None; self.progress.set_style( DownloadStatus::progress_style( + self.name_width, "downloading [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", ) .progress_chars("## "), @@ -371,6 +377,7 @@ impl DownloadStatus { pub(crate) fn finished(&self) { self.progress.set_style(DownloadStatus::progress_style( + self.name_width, "pending installation {total_bytes:>20}", )); self.progress.tick(); // A tick is needed for the new style to appear, as it is static. @@ -378,6 +385,7 @@ impl DownloadStatus { pub(crate) fn failed(&self) { self.progress.set_style(DownloadStatus::progress_style( + self.name_width, "download failed after {elapsed}", )); self.progress.finish(); @@ -385,14 +393,17 @@ impl DownloadStatus { pub(crate) fn retrying(&self) { *self.retry_time.lock().unwrap() = Some(Instant::now()); - self.progress - .set_style(DownloadStatus::progress_style("retrying download...")); + self.progress.set_style(DownloadStatus::progress_style( + self.name_width, + "retrying download...", + )); } pub(crate) fn unpack(&self, inner: T) -> ProgressBarIter { self.progress.reset(); self.progress.set_style( DownloadStatus::progress_style( + self.name_width, "unpacking [{bar:15}] {total_bytes:>11} ({bytes_per_sec}, ETA: {eta})", ) .progress_chars("## "), @@ -402,21 +413,25 @@ impl DownloadStatus { pub(crate) fn installing(&self) { self.progress.set_style( - DownloadStatus::progress_style("installing {spinner:.green} {total_bytes:>28}") - .tick_chars(r"|/-\ "), + DownloadStatus::progress_style( + self.name_width, + "installing {spinner:.green} {total_bytes:>28}", + ) + .tick_chars(r"|/-\ "), ); self.progress.enable_steady_tick(Duration::from_millis(100)); } pub(crate) fn installed(&self) { self.progress.set_style(DownloadStatus::progress_style( + self.name_width, "installed {total_bytes:>31}", )); self.progress.finish(); } - fn progress_style(suffix: &str) -> ProgressStyle { - let template = format!("{{msg:>13.bold}} {suffix}"); + fn progress_style(name_width: usize, suffix: &str) -> ProgressStyle { + let template = format!("{{msg:>{name_width}.bold}} {suffix}"); ProgressStyle::with_template(&template).unwrap() } } diff --git a/src/dist/manifestation.rs b/src/dist/manifestation.rs index 4b97074efb..c620b0184b 100644 --- a/src/dist/manifestation.rs +++ b/src/dist/manifestation.rs @@ -161,11 +161,24 @@ impl Manifestation { } } + const DEFAULT_MIN_NAME_WIDTH: usize = 13; + let max_name_width = update + .components_to_install + .iter() + // The same as the component name's length used in `ComponentBinary::new` + // As it's used for status output + .map(|component| new_manifest.short_name(component).len()) + .max() + .unwrap_or(0) + .max(DEFAULT_MIN_NAME_WIDTH); + // Download component packages and validate hashes let components = update .components_to_install .into_iter() - .filter_map(|component| ComponentBinary::new(component, &new_manifest, download_cfg)) + .filter_map(|component| { + ComponentBinary::new(component, &new_manifest, download_cfg, max_name_width) + }) .collect::>>()?; const DEFAULT_CONCURRENT_DOWNLOADS: usize = 2; @@ -416,7 +429,8 @@ impl Manifestation { .unwrap() .replace(DEFAULT_DIST_SERVER, dl_cfg.tmp_cx.dist_server.as_str()); - let status = dl_cfg.status_for("rust"); + let component_name = "rust"; + let status = dl_cfg.status_for(component_name, component_name.len()); let dl = dl_cfg .download_and_check(&url, Some(update_hash), Some(&status), ".tar.gz") .await?; @@ -752,6 +766,7 @@ impl<'a> ComponentBinary<'a> { component: Component, manifest: &'a Manifest, download_cfg: &'a DownloadCfg<'a>, + name_width: usize, ) -> Option> { Some(Ok(ComponentBinary { binary: match manifest.binary(&component) { @@ -759,7 +774,7 @@ impl<'a> ComponentBinary<'a> { Ok(None) => return None, Err(e) => return Some(Err(e)), }, - status: download_cfg.status_for(manifest.short_name(&component).to_owned()), + status: download_cfg.status_for(manifest.short_name(&component).to_owned(), name_width), component, manifest, download_cfg,