From 3b219d7171446be0826b18d0eb041635458bffdf Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 12:06:30 +0200 Subject: [PATCH 01/10] feat: Improve UX by adding console output --- src/lib.rs | 2 ++ src/pack.rs | 42 +++++++++++++++------- src/unpack.rs | 23 ++++++++++-- src/util.rs | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 src/util.rs diff --git a/src/lib.rs b/src/lib.rs index e00142d..b504f9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,12 @@ mod pack; mod unpack; +mod util; pub use pack::{pack, PackOptions}; use rattler_conda_types::Platform; use serde::{Deserialize, Serialize}; pub use unpack::{unarchive, unpack, UnpackOptions}; +pub use util::{create_progress_bar, get_size, InstallationProgressReporter}; pub const CHANNEL_DIRECTORY_NAME: &str = "channel"; pub const PIXI_PACK_METADATA_PATH: &str = "pixi-pack.json"; diff --git a/src/pack.rs b/src/pack.rs index bf899b1..56cb203 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -5,6 +5,7 @@ use std::{ }; use fxhash::FxHashMap; +use indicatif::HumanBytes; use rattler_index::{package_record_from_conda, package_record_from_tar_bz2}; use tokio::{ fs::{self, create_dir_all, File}, @@ -13,14 +14,16 @@ use tokio::{ use anyhow::Result; use futures::{stream, StreamExt, TryFutureExt, TryStreamExt}; -use indicatif::ProgressStyle; use rattler_conda_types::{package::ArchiveType, ChannelInfo, PackageRecord, Platform, RepoData}; use rattler_lock::{CondaPackage, LockFile, Package}; use rattler_networking::{AuthenticationMiddleware, AuthenticationStorage}; use reqwest_middleware::ClientWithMiddleware; use tokio_tar::Builder; -use crate::{PixiPackMetadata, CHANNEL_DIRECTORY_NAME, PIXI_PACK_METADATA_PATH}; +use crate::{ + create_progress_bar, get_size, PixiPackMetadata, CHANNEL_DIRECTORY_NAME, + PIXI_PACK_METADATA_PATH, +}; use anyhow::anyhow; /// Options for packing a pixi environment. @@ -89,31 +92,26 @@ pub async fn pack(options: PackOptions) -> Result<()> { // Download packages to temporary directory. tracing::info!( - "Downloading {} packages", + "Downloading {} packages...", conda_packages_from_lockfile.len() ); - let bar = indicatif::ProgressBar::new(conda_packages_from_lockfile.len() as u64); - bar.set_style( - ProgressStyle::with_template( - "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", - ) - .expect("could not set progress style") - .progress_chars("##-"), + println!( + "⏳ Downloading {} packages...", + conda_packages_from_lockfile.len() ); + let bar = create_progress_bar(conda_packages_from_lockfile.len() as u64); stream::iter(conda_packages_from_lockfile.iter()) .map(Ok) .try_for_each_concurrent(50, |package| async { download_package(&client, package, &channel_dir).await?; - bar.inc(1); - Ok(()) }) .await .map_err(|e: anyhow::Error| anyhow!("could not download package: {}", e))?; - bar.finish(); + bar.finish_and_clear(); let mut conda_packages: Vec<(String, PackageRecord)> = Vec::new(); @@ -133,6 +131,8 @@ pub async fn pack(options: PackOptions) -> Result<()> { .map(|(p, t)| (PathBuf::from(format!("{}{}", p, t.extension())), t)) }) .collect(); + + tracing::info!("Injecting {} packages", injected_packages.len()); for (path, archive_type) in injected_packages { // step 1: Derive PackageRecord from index.json inside the package let package_record = match archive_type { @@ -157,9 +157,11 @@ pub async fn pack(options: PackOptions) -> Result<()> { } // Create `repodata.json` files. + tracing::info!("Creating repodata.json files"); create_repodata_files(conda_packages.iter(), &channel_dir).await?; // Add pixi-pack.json containing metadata. + tracing::info!("Creating pixi-pack.json file"); let metadata_path = output_folder.path().join(PIXI_PACK_METADATA_PATH); let mut metadata_file = File::create(&metadata_path).await?; @@ -167,13 +169,27 @@ pub async fn pack(options: PackOptions) -> Result<()> { metadata_file.write_all(metadata.as_bytes()).await?; // Create environment file. + tracing::info!("Creating environment.yml file"); create_environment_file(output_folder.path(), conda_packages.iter().map(|(_, p)| p)).await?; // Pack = archive the contents. + tracing::info!("Creating archive at {}", options.output_file.display()); archive_directory(output_folder.path(), &options.output_file) .await .map_err(|e| anyhow!("could not archive directory: {}", e))?; + let output_size = HumanBytes(get_size(&options.output_file)?).to_string(); + tracing::info!( + "Created pack at {} with size {}.", + options.output_file.display(), + output_size + ); + println!( + "📦 Created pack at {} with size {}.", + options.output_file.display(), + output_size + ); + Ok(()) } diff --git a/src/unpack.rs b/src/unpack.rs index 32c16c6..a962275 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -22,7 +22,8 @@ use tokio_tar::Archive; use url::Url; use crate::{ - PixiPackMetadata, CHANNEL_DIRECTORY_NAME, DEFAULT_PIXI_PACK_VERSION, PIXI_PACK_METADATA_PATH, + InstallationProgressReporter, PixiPackMetadata, CHANNEL_DIRECTORY_NAME, + DEFAULT_PIXI_PACK_VERSION, PIXI_PACK_METADATA_PATH, }; /// Options for unpacking a pixi environment. @@ -41,6 +42,7 @@ pub async fn unpack(options: UnpackOptions) -> Result<()> { let channel_directory = unpack_dir.join(CHANNEL_DIRECTORY_NAME); + tracing::info!("Unarchiving pack to {}", unpack_dir.display()); unarchive(&options.pack_file, &unpack_dir) .await .map_err(|e| anyhow!("Could not unarchive: {}", e))?; @@ -49,10 +51,12 @@ pub async fn unpack(options: UnpackOptions) -> Result<()> { let target_prefix = options.output_directory.join("env"); + tracing::info!("Creating prefix at {}", target_prefix.display()); create_prefix(&channel_directory, &target_prefix) .await .map_err(|e| anyhow!("Could not create prefix: {}", e))?; + tracing::info!("Generating activation script"); create_activation_script( &options.output_directory, &target_prefix, @@ -61,6 +65,15 @@ pub async fn unpack(options: UnpackOptions) -> Result<()> { .await .map_err(|e| anyhow!("Could not create activation script: {}", e))?; + tracing::info!( + "Finished unpacking to {}.", + options.output_directory.display(), + ); + println!( + "💫 Finished unpacking to {}.", + options.output_directory.display() + ); + Ok(()) } @@ -158,8 +171,6 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { // extract packages to cache let package_cache = PackageCache::new(cache_dir); - let installer = Installer::default(); - let repodata_records: Vec = stream::iter(packages) .map(|(file_name, package_record)| { let cache_key = CacheKey::from(&package_record); @@ -198,6 +209,12 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { .await?; // Invariant: all packages are in the cache + tracing::info!("Installing {} packages", repodata_records.len()); + println!("⏳ Installing {} packages...", repodata_records.len()); + + let installer = Installer::default().with_reporter(InstallationProgressReporter::new( + repodata_records.len() as u64, + )); installer .with_package_cache(package_cache) .install(&target_prefix, repodata_records) diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..74c3bbc --- /dev/null +++ b/src/util.rs @@ -0,0 +1,97 @@ +use std::path::Path; + +use indicatif::{ProgressBar, ProgressStyle}; +use rattler::install::Reporter; +use rattler_conda_types::RepoDataRecord; + +/// Create a progress bar with default style. +pub fn create_progress_bar(length: u64) -> ProgressBar { + ProgressBar::new(length).with_style( + ProgressStyle::with_template( + "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", + ) + .expect("could not set progress style") + .progress_chars("##-"), + ) +} + +/// Progress reporter for installing packages. +pub struct InstallationProgressReporter { + pb: ProgressBar, +} + +impl InstallationProgressReporter { + pub fn new(length: u64) -> Self { + Self { + pb: create_progress_bar(length), + } + } +} + +impl Reporter for InstallationProgressReporter { + fn on_transaction_start( + &self, + _transaction: &rattler::install::Transaction< + rattler_conda_types::PrefixRecord, + RepoDataRecord, + >, + ) { + } + + fn on_transaction_operation_start(&self, _operation: usize) {} + fn on_download_start(&self, cache_entry: usize) -> usize { + cache_entry + } + + fn on_download_completed(&self, _download_idx: usize) {} + + fn on_link_start(&self, operation: usize, _record: &RepoDataRecord) -> usize { + operation + } + + fn on_link_complete(&self, _index: usize) {} + + fn on_transaction_operation_complete(&self, _operation: usize) { + self.pb.inc(1); + } + + fn on_populate_cache_start(&self, operation: usize, _record: &RepoDataRecord) -> usize { + operation + } + + fn on_validate_start(&self, cache_entry: usize) -> usize { + cache_entry + } + + fn on_validate_complete(&self, _validate_idx: usize) {} + + fn on_download_progress(&self, _download_idx: usize, _progress: u64, _total: Option) {} + + fn on_populate_cache_complete(&self, _cache_entry: usize) {} + + fn on_unlink_start( + &self, + operation: usize, + _record: &rattler_conda_types::PrefixRecord, + ) -> usize { + operation + } + + fn on_unlink_complete(&self, _index: usize) {} + + fn on_transaction_complete(&self) { + self.pb.finish_and_clear(); + } +} + +/// Get the size of a file or directory in bytes. +pub fn get_size>(path: P) -> std::io::Result { + let metadata = std::fs::metadata(&path)?; + let mut size = metadata.len(); + if metadata.is_dir() { + for entry in std::fs::read_dir(&path)? { + size += get_size(entry?.path())?; + } + } + Ok(size) +} From 9457527e48a3846aaf7bd32761f10307a5c82ff6 Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 12:07:00 +0200 Subject: [PATCH 02/10] Print to stderr --- src/pack.rs | 4 ++-- src/unpack.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pack.rs b/src/pack.rs index 56cb203..1383c28 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -95,7 +95,7 @@ pub async fn pack(options: PackOptions) -> Result<()> { "Downloading {} packages...", conda_packages_from_lockfile.len() ); - println!( + eprintln!( "⏳ Downloading {} packages...", conda_packages_from_lockfile.len() ); @@ -184,7 +184,7 @@ pub async fn pack(options: PackOptions) -> Result<()> { options.output_file.display(), output_size ); - println!( + eprintln!( "📦 Created pack at {} with size {}.", options.output_file.display(), output_size diff --git a/src/unpack.rs b/src/unpack.rs index a962275..373ec06 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -69,7 +69,7 @@ pub async fn unpack(options: UnpackOptions) -> Result<()> { "Finished unpacking to {}.", options.output_directory.display(), ); - println!( + eprintln!( "💫 Finished unpacking to {}.", options.output_directory.display() ); @@ -210,7 +210,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { // Invariant: all packages are in the cache tracing::info!("Installing {} packages", repodata_records.len()); - println!("⏳ Installing {} packages...", repodata_records.len()); + eprintln!("⏳ Installing {} packages...", repodata_records.len()); let installer = Installer::default().with_reporter(InstallationProgressReporter::new( repodata_records.len() as u64, From 5debaf94362ec9b496ce3a10ab08f987b28729ec Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 19:33:09 +0200 Subject: [PATCH 03/10] Add spinner for unpacking --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/lib.rs | 2 +- src/pack.rs | 11 ++++------- src/unpack.rs | 30 +++++++++++++++++++----------- src/util.rs | 41 ++++++++++++++++++++++++----------------- 6 files changed, 50 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90ac7be..ff75c76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2203,7 +2203,7 @@ dependencies = [ [[package]] name = "pixi-pack" -version = "0.1.2" +version = "0.1.3" dependencies = [ "anyhow", "async-std", diff --git a/Cargo.toml b/Cargo.toml index 595c7c0..9b53544 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pixi-pack" description = "A command line tool to pack and unpack conda environments for easy sharing" -version = "0.1.2" +version = "0.1.3" edition = "2021" [features] diff --git a/src/lib.rs b/src/lib.rs index b504f9c..3d0ea11 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ pub use pack::{pack, PackOptions}; use rattler_conda_types::Platform; use serde::{Deserialize, Serialize}; pub use unpack::{unarchive, unpack, UnpackOptions}; -pub use util::{create_progress_bar, get_size, InstallationProgressReporter}; +pub use util::{get_size, ProgressReporter}; pub const CHANNEL_DIRECTORY_NAME: &str = "channel"; pub const PIXI_PACK_METADATA_PATH: &str = "pixi-pack.json"; diff --git a/src/pack.rs b/src/pack.rs index 1383c28..4d26498 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -21,8 +21,7 @@ use reqwest_middleware::ClientWithMiddleware; use tokio_tar::Builder; use crate::{ - create_progress_bar, get_size, PixiPackMetadata, CHANNEL_DIRECTORY_NAME, - PIXI_PACK_METADATA_PATH, + get_size, PixiPackMetadata, ProgressReporter, CHANNEL_DIRECTORY_NAME, PIXI_PACK_METADATA_PATH, }; use anyhow::anyhow; @@ -99,19 +98,17 @@ pub async fn pack(options: PackOptions) -> Result<()> { "⏳ Downloading {} packages...", conda_packages_from_lockfile.len() ); - let bar = create_progress_bar(conda_packages_from_lockfile.len() as u64); - + let bar = ProgressReporter::new(conda_packages_from_lockfile.len() as u64); stream::iter(conda_packages_from_lockfile.iter()) .map(Ok) .try_for_each_concurrent(50, |package| async { download_package(&client, package, &channel_dir).await?; - bar.inc(1); + bar.pb.inc(1); Ok(()) }) .await .map_err(|e: anyhow::Error| anyhow!("could not download package: {}", e))?; - - bar.finish_and_clear(); + bar.pb.finish_and_clear(); let mut conda_packages: Vec<(String, PackageRecord)> = Vec::new(); diff --git a/src/unpack.rs b/src/unpack.rs index 373ec06..0c40a01 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -1,4 +1,7 @@ -use std::path::{Path, PathBuf}; +use std::{ + path::{Path, PathBuf}, + pin::Pin, +}; use anyhow::{anyhow, Result}; use futures::{ @@ -22,8 +25,8 @@ use tokio_tar::Archive; use url::Url; use crate::{ - InstallationProgressReporter, PixiPackMetadata, CHANNEL_DIRECTORY_NAME, - DEFAULT_PIXI_PACK_VERSION, PIXI_PACK_METADATA_PATH, + PixiPackMetadata, ProgressReporter, CHANNEL_DIRECTORY_NAME, DEFAULT_PIXI_PACK_VERSION, + PIXI_PACK_METADATA_PATH, }; /// Options for unpacking a pixi environment. @@ -43,6 +46,7 @@ pub async fn unpack(options: UnpackOptions) -> Result<()> { let channel_directory = unpack_dir.join(CHANNEL_DIRECTORY_NAME); tracing::info!("Unarchiving pack to {}", unpack_dir.display()); + eprintln!("📂 Unarchiving pack..."); unarchive(&options.pack_file, &unpack_dir) .await .map_err(|e| anyhow!("Could not unarchive: {}", e))?; @@ -150,11 +154,16 @@ pub async fn unarchive(archive_path: &Path, target_dir: &Path) -> Result<()> { let reader = tokio::io::BufReader::new(file); let mut archive = Archive::new(reader); - - archive - .unpack(target_dir) - .await - .map_err(|e| anyhow!("could not unpack archive: {}", e))?; + let mut entries = archive.entries()?; + let mut pinned = Pin::new(&mut entries); + + let spinner = ProgressReporter::new_spinner(); + while let Some(entry) = pinned.next().await { + let mut file = entry.map_err(|e| anyhow!("could not unpack archive: {}", e))?; + file.unpack_in::<&Path>(target_dir.as_ref()).await?; + spinner.pb.tick(); + } + spinner.pb.finish_and_clear(); Ok(()) } @@ -212,9 +221,8 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { tracing::info!("Installing {} packages", repodata_records.len()); eprintln!("⏳ Installing {} packages...", repodata_records.len()); - let installer = Installer::default().with_reporter(InstallationProgressReporter::new( - repodata_records.len() as u64, - )); + let installer = + Installer::default().with_reporter(ProgressReporter::new(repodata_records.len() as u64)); installer .with_package_cache(package_cache) .install(&target_prefix, repodata_records) diff --git a/src/util.rs b/src/util.rs index 74c3bbc..ce18589 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,31 +4,38 @@ use indicatif::{ProgressBar, ProgressStyle}; use rattler::install::Reporter; use rattler_conda_types::RepoDataRecord; -/// Create a progress bar with default style. -pub fn create_progress_bar(length: u64) -> ProgressBar { - ProgressBar::new(length).with_style( - ProgressStyle::with_template( - "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", - ) - .expect("could not set progress style") - .progress_chars("##-"), - ) +/// Progress reporter that wraps a progress bar or spinner with default styles. +pub struct ProgressReporter { + pub pb: ProgressBar, } -/// Progress reporter for installing packages. -pub struct InstallationProgressReporter { - pb: ProgressBar, -} - -impl InstallationProgressReporter { +impl ProgressReporter { pub fn new(length: u64) -> Self { Self { - pb: create_progress_bar(length), + pb: ProgressBar::new(length).with_style( + ProgressStyle::with_template( + "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", + ) + .expect("could not set progress style") + .progress_chars("##-"), + ), } } + + pub fn new_spinner() -> Self { + Self { + pb: ProgressBar::new_spinner(), + } + } +} + +impl From for ProgressReporter { + fn from(pb: ProgressBar) -> Self { + ProgressReporter { pb } + } } -impl Reporter for InstallationProgressReporter { +impl Reporter for ProgressReporter { fn on_transaction_start( &self, _transaction: &rattler::install::Transaction< From 843e069d0daa749f4256c2e2a7f96231606deeb9 Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 19:55:15 +0200 Subject: [PATCH 04/10] Revert to no spinner --- src/unpack.rs | 26 +++++++++----------------- src/util.rs | 14 +------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/src/unpack.rs b/src/unpack.rs index 0c40a01..87a037f 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -1,7 +1,4 @@ -use std::{ - path::{Path, PathBuf}, - pin::Pin, -}; +use std::path::{Path, PathBuf}; use anyhow::{anyhow, Result}; use futures::{ @@ -46,7 +43,6 @@ pub async fn unpack(options: UnpackOptions) -> Result<()> { let channel_directory = unpack_dir.join(CHANNEL_DIRECTORY_NAME); tracing::info!("Unarchiving pack to {}", unpack_dir.display()); - eprintln!("📂 Unarchiving pack..."); unarchive(&options.pack_file, &unpack_dir) .await .map_err(|e| anyhow!("Could not unarchive: {}", e))?; @@ -154,16 +150,11 @@ pub async fn unarchive(archive_path: &Path, target_dir: &Path) -> Result<()> { let reader = tokio::io::BufReader::new(file); let mut archive = Archive::new(reader); - let mut entries = archive.entries()?; - let mut pinned = Pin::new(&mut entries); - - let spinner = ProgressReporter::new_spinner(); - while let Some(entry) = pinned.next().await { - let mut file = entry.map_err(|e| anyhow!("could not unpack archive: {}", e))?; - file.unpack_in::<&Path>(target_dir.as_ref()).await?; - spinner.pb.tick(); - } - spinner.pb.finish_and_clear(); + + archive + .unpack(target_dir) + .await + .map_err(|e| anyhow!("could not unpack archive: {}", e))?; Ok(()) } @@ -177,7 +168,10 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { .map_err(|e| anyhow!("could not create temporary directory: {}", e))? .into_path(); + eprintln!("⏳ Installing {} packages...", packages.len()); + // extract packages to cache + tracing::info!("Creating cache with {} packages", packages.len()); let package_cache = PackageCache::new(cache_dir); let repodata_records: Vec = stream::iter(packages) @@ -219,8 +213,6 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { // Invariant: all packages are in the cache tracing::info!("Installing {} packages", repodata_records.len()); - eprintln!("⏳ Installing {} packages...", repodata_records.len()); - let installer = Installer::default().with_reporter(ProgressReporter::new(repodata_records.len() as u64)); installer diff --git a/src/util.rs b/src/util.rs index ce18589..3debbc4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,7 +4,7 @@ use indicatif::{ProgressBar, ProgressStyle}; use rattler::install::Reporter; use rattler_conda_types::RepoDataRecord; -/// Progress reporter that wraps a progress bar or spinner with default styles. +/// Progress reporter that wraps a progress bar with default styles. pub struct ProgressReporter { pub pb: ProgressBar, } @@ -21,18 +21,6 @@ impl ProgressReporter { ), } } - - pub fn new_spinner() -> Self { - Self { - pb: ProgressBar::new_spinner(), - } - } -} - -impl From for ProgressReporter { - fn from(pb: ProgressBar) -> Self { - ProgressReporter { pb } - } } impl Reporter for ProgressReporter { From af0f969c6df83b360070997b9c891170329355f5 Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 19:56:23 +0200 Subject: [PATCH 05/10] Fix --- src/unpack.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unpack.rs b/src/unpack.rs index 87a037f..6e19145 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -169,6 +169,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { .into_path(); eprintln!("⏳ Installing {} packages...", packages.len()); + let reporter = ProgressReporter::new(packages.len() as u64); // extract packages to cache tracing::info!("Creating cache with {} packages", packages.len()); @@ -213,8 +214,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { // Invariant: all packages are in the cache tracing::info!("Installing {} packages", repodata_records.len()); - let installer = - Installer::default().with_reporter(ProgressReporter::new(repodata_records.len() as u64)); + let installer = Installer::default().with_reporter(reporter); installer .with_package_cache(package_cache) .install(&target_prefix, repodata_records) From fefabe87d88feb8dcc0d33fe769a46dc076fe42e Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 20:19:33 +0200 Subject: [PATCH 06/10] Fix progress bar for unpacking --- src/unpack.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/unpack.rs b/src/unpack.rs index 6e19145..07d4ce9 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -168,7 +168,10 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { .map_err(|e| anyhow!("could not create temporary directory: {}", e))? .into_path(); - eprintln!("⏳ Installing {} packages...", packages.len()); + eprintln!( + "⏳ Extracting and installing {} packages...", + packages.len() + ); let reporter = ProgressReporter::new(packages.len() as u64); // extract packages to cache @@ -204,6 +207,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { ) .await .map_err(|e| anyhow!("could not extract package: {}", e))?; + reporter.pb.inc(1); Ok::(repodata_record) } @@ -211,10 +215,12 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { .buffer_unordered(50) .try_collect() .await?; + reporter.pb.finish_and_clear(); // Invariant: all packages are in the cache tracing::info!("Installing {} packages", repodata_records.len()); - let installer = Installer::default().with_reporter(reporter); + let installer = Installer::default() + .with_reporter::(ProgressReporter::new(repodata_records.len() as u64)); installer .with_package_cache(package_cache) .install(&target_prefix, repodata_records) From c9b918dd4cdf81c2a18b2d8058664f01cd127fcf Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 20:29:05 +0200 Subject: [PATCH 07/10] Remove total length from bar --- src/unpack.rs | 5 ++--- src/util.rs | 8 +++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/unpack.rs b/src/unpack.rs index 07d4ce9..29e6e53 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -172,7 +172,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { "⏳ Extracting and installing {} packages...", packages.len() ); - let reporter = ProgressReporter::new(packages.len() as u64); + let reporter = ProgressReporter::new(2 * packages.len() as u64); // extract packages to cache tracing::info!("Creating cache with {} packages", packages.len()); @@ -219,8 +219,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { // Invariant: all packages are in the cache tracing::info!("Installing {} packages", repodata_records.len()); - let installer = Installer::default() - .with_reporter::(ProgressReporter::new(repodata_records.len() as u64)); + let installer = Installer::default().with_reporter::(reporter); installer .with_package_cache(package_cache) .install(&target_prefix, repodata_records) diff --git a/src/util.rs b/src/util.rs index 3debbc4..3000c65 100644 --- a/src/util.rs +++ b/src/util.rs @@ -13,11 +13,9 @@ impl ProgressReporter { pub fn new(length: u64) -> Self { Self { pb: ProgressBar::new(length).with_style( - ProgressStyle::with_template( - "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", - ) - .expect("could not set progress style") - .progress_chars("##-"), + ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {msg}") + .expect("could not set progress style") + .progress_chars("##-"), ), } } From c2c809a9e4302871d7ea9b5792fac6678c275bd8 Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 20:35:01 +0200 Subject: [PATCH 08/10] Fix bug --- src/unpack.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/unpack.rs b/src/unpack.rs index 29e6e53..5f02467 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -215,11 +215,10 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { .buffer_unordered(50) .try_collect() .await?; - reporter.pb.finish_and_clear(); // Invariant: all packages are in the cache tracing::info!("Installing {} packages", repodata_records.len()); - let installer = Installer::default().with_reporter::(reporter); + let installer = Installer::default().with_reporter(reporter); installer .with_package_cache(package_cache) .install(&target_prefix, repodata_records) From ad11f659c24e0f828594098aecca9e3c6e04abc0 Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Fri, 7 Jun 2024 20:43:10 +0200 Subject: [PATCH 09/10] Fix bug --- src/util.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/util.rs b/src/util.rs index 3000c65..2faddac 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::{path::Path, time::Duration}; use indicatif::{ProgressBar, ProgressStyle}; use rattler::install::Reporter; @@ -11,13 +11,13 @@ pub struct ProgressReporter { impl ProgressReporter { pub fn new(length: u64) -> Self { - Self { - pb: ProgressBar::new(length).with_style( - ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {msg}") - .expect("could not set progress style") - .progress_chars("##-"), - ), - } + let pb = ProgressBar::new(length).with_style( + ProgressStyle::with_template("[{elapsed_precise}] {bar:40.cyan/blue} {msg}") + .expect("could not set progress style") + .progress_chars("##-"), + ); + pb.enable_steady_tick(Duration::from_millis(500)); + Self { pb } } } From 59cdac6a0efc9cbb69ae4a617e8ba88f4de656cc Mon Sep 17 00:00:00 2001 From: Daniel Elsner Date: Sat, 8 Jun 2024 10:00:39 +0200 Subject: [PATCH 10/10] Remove install progress reporter again --- src/unpack.rs | 4 ++-- src/util.rs | 58 --------------------------------------------------- 2 files changed, 2 insertions(+), 60 deletions(-) diff --git a/src/unpack.rs b/src/unpack.rs index 5f02467..c7dbd23 100644 --- a/src/unpack.rs +++ b/src/unpack.rs @@ -172,7 +172,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { "⏳ Extracting and installing {} packages...", packages.len() ); - let reporter = ProgressReporter::new(2 * packages.len() as u64); + let reporter = ProgressReporter::new(packages.len() as u64); // extract packages to cache tracing::info!("Creating cache with {} packages", packages.len()); @@ -218,7 +218,7 @@ async fn create_prefix(channel_dir: &Path, target_prefix: &Path) -> Result<()> { // Invariant: all packages are in the cache tracing::info!("Installing {} packages", repodata_records.len()); - let installer = Installer::default().with_reporter(reporter); + let installer = Installer::default(); installer .with_package_cache(package_cache) .install(&target_prefix, repodata_records) diff --git a/src/util.rs b/src/util.rs index 2faddac..9cc0c04 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,6 @@ use std::{path::Path, time::Duration}; use indicatif::{ProgressBar, ProgressStyle}; -use rattler::install::Reporter; -use rattler_conda_types::RepoDataRecord; /// Progress reporter that wraps a progress bar with default styles. pub struct ProgressReporter { @@ -21,62 +19,6 @@ impl ProgressReporter { } } -impl Reporter for ProgressReporter { - fn on_transaction_start( - &self, - _transaction: &rattler::install::Transaction< - rattler_conda_types::PrefixRecord, - RepoDataRecord, - >, - ) { - } - - fn on_transaction_operation_start(&self, _operation: usize) {} - fn on_download_start(&self, cache_entry: usize) -> usize { - cache_entry - } - - fn on_download_completed(&self, _download_idx: usize) {} - - fn on_link_start(&self, operation: usize, _record: &RepoDataRecord) -> usize { - operation - } - - fn on_link_complete(&self, _index: usize) {} - - fn on_transaction_operation_complete(&self, _operation: usize) { - self.pb.inc(1); - } - - fn on_populate_cache_start(&self, operation: usize, _record: &RepoDataRecord) -> usize { - operation - } - - fn on_validate_start(&self, cache_entry: usize) -> usize { - cache_entry - } - - fn on_validate_complete(&self, _validate_idx: usize) {} - - fn on_download_progress(&self, _download_idx: usize, _progress: u64, _total: Option) {} - - fn on_populate_cache_complete(&self, _cache_entry: usize) {} - - fn on_unlink_start( - &self, - operation: usize, - _record: &rattler_conda_types::PrefixRecord, - ) -> usize { - operation - } - - fn on_unlink_complete(&self, _index: usize) {} - - fn on_transaction_complete(&self) { - self.pb.finish_and_clear(); - } -} - /// Get the size of a file or directory in bytes. pub fn get_size>(path: P) -> std::io::Result { let metadata = std::fs::metadata(&path)?;