this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(zip): add progress bars during compression

+39 -10
+39 -10
src/backends/zip.rs
··· 1 + use super::containers::total_input_bytes; 2 + use crate::progress::{OutputTarget, ProgressArgs, ProgressReader, create_progress_bar}; 1 3 use crate::utils::{ 2 4 CmprssInput, CmprssOutput, CommonArgs, CompressionLevelValidator, Compressor, 3 5 DefaultCompressionValidator, ExtractedTarget, LevelArgs, Result, 4 6 }; 5 7 use anyhow::bail; 6 8 use clap::Args; 9 + use indicatif::ProgressBar; 7 10 use std::fs::File; 8 11 use std::io::{self, Seek, SeekFrom, Write}; 9 12 use std::path::Path; ··· 19 22 20 23 #[clap(flatten)] 21 24 pub level_args: LevelArgs, 25 + 26 + #[clap(flatten)] 27 + pub progress_args: ProgressArgs, 22 28 } 23 29 24 30 #[derive(Clone)] 25 31 pub struct Zip { 26 32 pub compression_level: i32, 33 + pub progress_args: ProgressArgs, 27 34 } 28 35 29 36 impl Default for Zip { 30 37 fn default() -> Self { 31 38 Zip { 32 39 compression_level: DefaultCompressionValidator.default_level(), 40 + progress_args: ProgressArgs::default(), 33 41 } 34 42 } 35 43 } ··· 38 46 pub fn new(args: &ZipArgs) -> Zip { 39 47 Zip { 40 48 compression_level: args.level_args.resolve(&DefaultCompressionValidator), 49 + progress_args: args.progress_args, 41 50 } 42 51 } 43 52 ··· 47 56 .compression_level(Some(self.compression_level as i64)) 48 57 } 49 58 50 - fn compress_to_file<W: Write + Seek>(&self, input: CmprssInput, writer: W) -> Result { 59 + fn compress_to_file<W: Write + Seek>( 60 + &self, 61 + input: CmprssInput, 62 + writer: W, 63 + bar: Option<&ProgressBar>, 64 + ) -> Result { 51 65 let mut zip_writer = ZipWriter::new(writer); 52 66 let options = self.file_options(); 53 67 ··· 57 71 if path.is_file() { 58 72 let name = path.file_name().unwrap().to_string_lossy(); 59 73 zip_writer.start_file(name, options)?; 60 - let mut f = File::open(&path)?; 61 - io::copy(&mut f, &mut zip_writer)?; 74 + let f = File::open(&path)?; 75 + let mut reader = ProgressReader::new(f, bar.cloned()); 76 + io::copy(&mut reader, &mut zip_writer)?; 62 77 } else if path.is_dir() { 63 78 // Use the directory as the base and add its contents 64 79 let base = path.parent().unwrap_or(&path); 65 - add_directory(&mut zip_writer, base, &path, options)?; 80 + add_directory(&mut zip_writer, base, &path, options, bar)?; 66 81 } else { 67 82 bail!("zip does not support this file type"); 68 83 } ··· 100 115 fn compress(&self, input: CmprssInput, output: CmprssOutput) -> Result { 101 116 match output { 102 117 CmprssOutput::Path(ref path) => { 118 + let total = match &input { 119 + CmprssInput::Path(paths) => Some(total_input_bytes(paths)), 120 + _ => None, 121 + }; 122 + let bar = 123 + create_progress_bar(total, self.progress_args.progress, OutputTarget::File); 103 124 let file = File::create(path)?; 104 - self.compress_to_file(input, file) 125 + self.compress_to_file(input, file, bar.as_ref())?; 126 + if let Some(b) = bar { 127 + b.finish(); 128 + } 129 + Ok(()) 105 130 } 106 131 CmprssOutput::Pipe(mut pipe) => { 107 132 // Create a temporary file to write the zip to 108 133 let mut temp_file = tempfile()?; 109 - self.compress_to_file(input, &mut temp_file)?; 134 + self.compress_to_file(input, &mut temp_file, None)?; 110 135 111 136 // Reset the file position to the beginning 112 137 temp_file.seek(SeekFrom::Start(0))?; ··· 117 142 } 118 143 CmprssOutput::Writer(mut writer) => { 119 144 let mut temp_file = tempfile()?; 120 - self.compress_to_file(input, &mut temp_file)?; 145 + self.compress_to_file(input, &mut temp_file, None)?; 121 146 temp_file.seek(SeekFrom::Start(0))?; 122 147 io::copy(&mut temp_file, &mut writer)?; 123 148 Ok(()) ··· 230 255 base: &Path, 231 256 path: &Path, 232 257 options: FileOptions<'static, ()>, 258 + bar: Option<&ProgressBar>, 233 259 ) -> Result { 234 260 for entry in std::fs::read_dir(path)? { 235 261 let entry = entry?; ··· 242 268 .replace('\\', "/"); 243 269 if entry_path.is_file() { 244 270 zip.start_file(name, options)?; 245 - let mut f = File::open(&entry_path)?; 246 - io::copy(&mut f, zip)?; 271 + let f = File::open(&entry_path)?; 272 + let mut reader = ProgressReader::new(f, bar.cloned()); 273 + io::copy(&mut reader, zip)?; 247 274 } else if entry_path.is_dir() { 248 275 // Ensure directory entry ends with '/' 249 276 let dir_name = name.clone() + "/"; 250 277 zip.add_directory(dir_name, options)?; 251 - add_directory(zip, base, &entry_path, options)?; 278 + add_directory(zip, base, &entry_path, options, bar)?; 252 279 } 253 280 } 254 281 Ok(()) ··· 281 308 fn test_zip_fast_compression() -> Result { 282 309 let fast_compressor = Zip { 283 310 compression_level: 1, 311 + progress_args: ProgressArgs::default(), 284 312 }; 285 313 test_compression(&fast_compressor) 286 314 } ··· 290 318 fn test_zip_best_compression() -> Result { 291 319 let best_compressor = Zip { 292 320 compression_level: 9, 321 + progress_args: ProgressArgs::default(), 293 322 }; 294 323 test_compression(&best_compressor) 295 324 }