diff --git a/src/dist/download.rs b/src/dist/download.rs index e8989a3270..946be5e30e 100644 --- a/src/dist/download.rs +++ b/src/dist/download.rs @@ -1,12 +1,13 @@ use std::borrow::Cow; use std::fs; +use std::io::Read; use std::ops; use std::path::{Path, PathBuf}; use std::sync::Mutex; use std::time::{Duration, Instant}; use anyhow::{Context, Result, anyhow}; -use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle}; +use indicatif::{MultiProgress, ProgressBar, ProgressBarIter, ProgressDrawTarget, ProgressStyle}; use sha2::{Digest, Sha256}; use tracing::{debug, warn}; use url::Url; @@ -300,6 +301,18 @@ impl DownloadStatus { ); } + pub(crate) fn unpack(&self, inner: T) -> ProgressBarIter { + self.progress.reset(); + self.progress.set_style( + ProgressStyle::with_template( + "{msg:>12.bold} unpacking {spinner:.green} {total_bytes:>18}", + ) + .unwrap() + .tick_chars(r"|/-\ "), + ); + self.progress.wrap_read(inner) + } + pub(crate) fn installing(&self) { self.progress.set_style( ProgressStyle::with_template( @@ -321,8 +334,7 @@ impl DownloadStatus { fn file_hash(path: &Path) -> Result { let mut hasher = Sha256::new(); - let mut downloaded = utils::FileReaderWithProgress::new_file(path)?; - use std::io::Read; + let mut downloaded = utils::buffered(path)?; let mut buf = vec![0; 32768]; while let Ok(n) = downloaded.read(&mut buf) { if n == 0 { diff --git a/src/dist/manifestation.rs b/src/dist/manifestation.rs index 85b839bd5c..c8266a04f4 100644 --- a/src/dist/manifestation.rs +++ b/src/dist/manifestation.rs @@ -407,7 +407,7 @@ impl Manifestation { } // Install all the components in the installer - let reader = utils::FileReaderWithProgress::new_file(&installer_file)?; + let reader = utils::buffered(&installer_file)?; let package = DirectoryPackage::compressed(reader, CompressionKind::GZip, dl_cfg)?; for component in package.components() { tx = package.install(&self.installation, &component, None, tx)?; @@ -720,9 +720,7 @@ impl<'a> ComponentBinary<'a> { let short_pkg_name = component.short_name_in_manifest(); let short_name = component.short_name(self.manifest); - self.status.installing(); - - let reader = utils::FileReaderWithProgress::new_file(&installer_file)?; + let reader = self.status.unpack(utils::buffered(&installer_file)?); let package = DirectoryPackage::compressed(reader, self.binary.compression, self.download_cfg)?; @@ -732,6 +730,7 @@ impl<'a> ComponentBinary<'a> { return Err(RustupError::CorruptComponent(short_name).into()); } + self.status.installing(); let tx = package.install( &manifestation.installation, &pkg_name, diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 0eb30d5387..a20c8998ff 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -8,7 +8,7 @@ use std::ops::{BitAnd, BitAndAssign}; use std::path::{Path, PathBuf}; use std::process::ExitStatus; -use anyhow::{Context, Result, anyhow, bail}; +use anyhow::{Context, Result, anyhow}; use retry::delay::{Fibonacci, jitter}; use retry::{OperationResult, retry}; use tracing::{debug, info, warn}; @@ -444,40 +444,13 @@ pub(crate) fn delete_dir_contents_following_links(dir_path: &Path) { } } -pub(crate) struct FileReaderWithProgress { - fh: BufReader, - nbytes: u64, -} - -impl FileReaderWithProgress { - pub(crate) fn new_file(path: &Path) -> Result { - let fh = match File::open(path) { - Ok(fh) => fh, - Err(_) => { - bail!(RustupError::ReadingFile { - name: "downloaded", - path: path.to_path_buf(), - }) - } - }; - - // Inform the tracker of the file size - Ok(FileReaderWithProgress { - fh: BufReader::with_capacity(8 * 1024 * 1024, fh), - nbytes: 0, - }) - } -} - -impl io::Read for FileReaderWithProgress { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - match self.fh.read(buf) { - Ok(nbytes) => { - self.nbytes += nbytes as u64; - Ok(nbytes) - } - Err(e) => Err(e), - } +pub(crate) fn buffered(path: &Path) -> Result, anyhow::Error> { + match File::open(path) { + Ok(fh) => Ok(BufReader::with_capacity(8 * 1024 * 1024, fh)), + Err(_) => Err(anyhow!(RustupError::ReadingFile { + name: "downloaded", + path: path.to_path_buf(), + })), } }