diff --git a/src/dist/download.rs b/src/dist/download.rs index e9fc404d86..6342d4cdd3 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, info, warn}; use url::Url; @@ -389,6 +390,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 [{bar:20}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})", + ) + .unwrap() + .progress_chars("## ") + ); + self.progress.wrap_read(inner) + } + pub(crate) fn installing(&self) { self.progress.set_style( ProgressStyle::with_template( @@ -410,8 +423,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 ea20b061d6..0aea681419 100644 --- a/src/dist/manifestation.rs +++ b/src/dist/manifestation.rs @@ -399,7 +399,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 temp_dir = dl_cfg.tmp_cx.new_directory()?; let io_executor = get_executor( unpack_ram(IO_CHUNK_SIZE, dl_cfg.process.unpack_ram()?), @@ -685,14 +685,12 @@ impl<'a> ComponentBinary<'a> { let short_pkg_name = self.component.short_name_in_manifest(); let short_name = self.manifest.short_name(&self.component); - self.status.installing(); - - let reader = utils::FileReaderWithProgress::new_file(&installer_file)?; let temp_dir = self.download_cfg.tmp_cx.new_directory()?; let io_executor = get_executor( unpack_ram(IO_CHUNK_SIZE, self.download_cfg.process.unpack_ram()?), self.download_cfg.process.io_thread_count()?, ); + let reader = self.status.unpack(utils::buffered(&installer_file)?); let package = DirectoryPackage::compressed(reader, self.binary.compression, temp_dir, io_executor)?; @@ -702,6 +700,7 @@ impl<'a> ComponentBinary<'a> { return Err(RustupError::CorruptComponent(short_name.to_owned()).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 1fa99388d7..8840db1eb6 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}; @@ -441,40 +441,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(), + })), } }