From b55336f0934012e690f2fed210b49f5f3fe3fab3 Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sun, 26 Nov 2023 13:55:35 +0100 Subject: [PATCH 1/5] Add simple download progress tracker --- crates/packaging/src/https.rs | 57 ++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/crates/packaging/src/https.rs b/crates/packaging/src/https.rs index 3ef428de5f..ec1df1291b 100644 --- a/crates/packaging/src/https.rs +++ b/crates/packaging/src/https.rs @@ -1,5 +1,5 @@ use std::{ - io::{self, Read}, + io::{self, Read, Write}, path::Path, }; @@ -275,9 +275,17 @@ pub fn download_and_hash( Encoding::new(content_encoding, url)? }; - // Use .take to prevent a malicious server from sending back bytes - // until system resources are exhausted! - decompress_into(dest_dir, encoding, resp.take(max_download_bytes)) + if let Some(content_len) = resp.content_length() { + // Print download progress to stdout if we know the content length + // + // Use .take to prevent a malicious server from sending back bytes + // until system resources are exhausted! + let resp = ProgressReporter::new(resp.take(max_download_bytes), content_len as usize); + + decompress_into(dest_dir, encoding, resp) + } else { + decompress_into(dest_dir, encoding, resp.take(max_download_bytes)) + } } /// The content encodings we support @@ -405,3 +413,44 @@ impl Read for HashReader { Ok(bytes_read) } } + +/// Prints download progress to stdout +struct ProgressReporter { + read: usize, + total: usize, + last_reported: usize, + reader: R, +} + +impl ProgressReporter { + fn new(reader: R, total: usize) -> Self { + ProgressReporter { + read: 0, + last_reported: 0, + total, + reader, + } + } +} + +impl Read for ProgressReporter { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let size = self.reader.read(buf)?; + + self.read += size; + + print!( + "\u{001b}[2K\u{001b}[G[{:.1} / {:.1} MB]", + self.read as f32 / 1_000_000.0, + self.total as f32 / 1_000_000.0, + ); + std::io::stdout().flush()?; + self.last_reported = self.read; + + if self.read >= self.total { + println!(""); + } + + Ok(size) + } +} From 7f82f8da2bf4f653e4bb2f9368e6b14590da027f Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sun, 26 Nov 2023 15:12:26 +0100 Subject: [PATCH 2/5] Remove unused variable --- crates/packaging/src/https.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/packaging/src/https.rs b/crates/packaging/src/https.rs index ec1df1291b..dd6fd825ae 100644 --- a/crates/packaging/src/https.rs +++ b/crates/packaging/src/https.rs @@ -418,7 +418,6 @@ impl Read for HashReader { struct ProgressReporter { read: usize, total: usize, - last_reported: usize, reader: R, } @@ -426,7 +425,6 @@ impl ProgressReporter { fn new(reader: R, total: usize) -> Self { ProgressReporter { read: 0, - last_reported: 0, total, reader, } @@ -445,7 +443,6 @@ impl Read for ProgressReporter { self.total as f32 / 1_000_000.0, ); std::io::stdout().flush()?; - self.last_reported = self.read; if self.read >= self.total { println!(""); From aad1c0682cbae188cf3f658ed931c98516236e6f Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Mon, 27 Nov 2023 18:11:41 +0100 Subject: [PATCH 3/5] Add progress reporting even when total size is unknown --- crates/packaging/src/https.rs | 40 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/crates/packaging/src/https.rs b/crates/packaging/src/https.rs index dd6fd825ae..609d405de9 100644 --- a/crates/packaging/src/https.rs +++ b/crates/packaging/src/https.rs @@ -275,17 +275,12 @@ pub fn download_and_hash( Encoding::new(content_encoding, url)? }; - if let Some(content_len) = resp.content_length() { - // Print download progress to stdout if we know the content length - // - // Use .take to prevent a malicious server from sending back bytes - // until system resources are exhausted! - let resp = ProgressReporter::new(resp.take(max_download_bytes), content_len as usize); - - decompress_into(dest_dir, encoding, resp) - } else { - decompress_into(dest_dir, encoding, resp.take(max_download_bytes)) - } + let content_length = resp.content_length().map(|n| n as usize); + + // Use .take to prevent a malicious server from sending back bytes + // until system resources are exhausted! + let resp = ProgressReporter::new(resp.take(max_download_bytes), content_length); + decompress_into(dest_dir, encoding, resp) } /// The content encodings we support @@ -417,12 +412,12 @@ impl Read for HashReader { /// Prints download progress to stdout struct ProgressReporter { read: usize, - total: usize, + total: Option, reader: R, } impl ProgressReporter { - fn new(reader: R, total: usize) -> Self { + fn new(reader: R, total: Option) -> Self { ProgressReporter { read: 0, total, @@ -437,14 +432,21 @@ impl Read for ProgressReporter { self.read += size; - print!( - "\u{001b}[2K\u{001b}[G[{:.1} / {:.1} MB]", - self.read as f32 / 1_000_000.0, - self.total as f32 / 1_000_000.0, - ); + if let Some(total) = self.total { + print!( + "\u{001b}[2K\u{001b}[G[{:.1} / {:.1} MB]", + self.read as f32 / 1_000_000.0, + total as f32 / 1_000_000.0, + ); + } else { + print!( + "\u{001b}[2K\u{001b}[G[{:.1} MB]", + self.read as f32 / 1_000_000.0, + ); + } std::io::stdout().flush()?; - if self.read >= self.total { + if self.total.is_some_and(|total| self.read >= total) { println!(""); } From f2f58b062d5cf4e0aaf087c63996bef627e46f3c Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Thu, 30 Nov 2023 16:17:38 +0100 Subject: [PATCH 4/5] Remove unneeded println arg --- crates/packaging/src/https.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/packaging/src/https.rs b/crates/packaging/src/https.rs index 609d405de9..76a171bc4c 100644 --- a/crates/packaging/src/https.rs +++ b/crates/packaging/src/https.rs @@ -447,7 +447,7 @@ impl Read for ProgressReporter { std::io::stdout().flush()?; if self.total.is_some_and(|total| self.read >= total) { - println!(""); + println!(); } Ok(size) From 6f3588186c8701414d6f5ac573f9d1a0405a40d7 Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Fri, 1 Dec 2023 19:48:36 +0100 Subject: [PATCH 5/5] Print download progress to stderr instead --- crates/packaging/src/https.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/packaging/src/https.rs b/crates/packaging/src/https.rs index 76a171bc4c..5928b23dad 100644 --- a/crates/packaging/src/https.rs +++ b/crates/packaging/src/https.rs @@ -433,21 +433,21 @@ impl Read for ProgressReporter { self.read += size; if let Some(total) = self.total { - print!( + eprint!( "\u{001b}[2K\u{001b}[G[{:.1} / {:.1} MB]", self.read as f32 / 1_000_000.0, total as f32 / 1_000_000.0, ); } else { - print!( + eprint!( "\u{001b}[2K\u{001b}[G[{:.1} MB]", self.read as f32 / 1_000_000.0, ); } - std::io::stdout().flush()?; + std::io::stderr().flush()?; if self.total.is_some_and(|total| self.read >= total) { - println!(); + eprintln!(); } Ok(size)