From 62f3d78f440d0d554def265e004ea4d8846eb124 Mon Sep 17 00:00:00 2001 From: ttyS3 Date: Sat, 30 Nov 2024 16:27:02 +0000 Subject: [PATCH] refactor(decompress): refactor function to use DecompressOptions struct to make linter happy (too_many_arguments) --- src/commands/decompress.rs | 100 +++++++++++++++++++------------------ src/commands/mod.rs | 13 ++--- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/src/commands/decompress.rs b/src/commands/decompress.rs index a1d7e84..4a616e2 100644 --- a/src/commands/decompress.rs +++ b/src/commands/decompress.rs @@ -26,24 +26,26 @@ use crate::{ trait ReadSeek: Read + io::Seek {} impl ReadSeek for T {} +pub struct DecompressOptions<'a> { + pub input_file_path: &'a Path, + pub formats: Vec, + pub output_dir: &'a Path, + pub output_file_path: PathBuf, + pub question_policy: QuestionPolicy, + pub quiet: bool, + pub password: Option<&'a [u8]>, + pub remove: bool, +} + /// Decompress a file /// /// File at input_file_path is opened for reading, example: "archive.tar.gz" /// formats contains each format necessary for decompression, example: [Gz, Tar] (in decompression order) /// output_dir it's where the file will be decompressed to, this function assumes that the directory exists /// output_file_path is only used when extracting single file formats, not archive formats like .tar or .zip -pub fn decompress_file( - input_file_path: &Path, - formats: Vec, - output_dir: &Path, - output_file_path: PathBuf, - question_policy: QuestionPolicy, - quiet: bool, - password: Option<&[u8]>, - remove: bool, -) -> crate::Result<()> { - assert!(output_dir.exists()); - let input_is_stdin = is_path_stdin(input_file_path); +pub fn decompress_file(options: DecompressOptions) -> crate::Result<()> { + assert!(options.output_dir.exists()); + let input_is_stdin = is_path_stdin(options.input_file_path); // Zip archives are special, because they require io::Seek, so it requires it's logic separated // from decoder chaining. @@ -55,7 +57,7 @@ pub fn decompress_file( if let [Extension { compression_formats: [Zip], .. - }] = formats.as_slice() + }] = options.formats.as_slice() { let mut vec = vec![]; let reader: Box = if input_is_stdin { @@ -63,14 +65,14 @@ pub fn decompress_file( io::copy(&mut io::stdin(), &mut vec)?; Box::new(io::Cursor::new(vec)) } else { - Box::new(fs::File::open(input_file_path)?) + Box::new(fs::File::open(options.input_file_path)?) }; let zip_archive = zip::ZipArchive::new(reader)?; let files_unpacked = if let ControlFlow::Continue(files) = smart_unpack( - |output_dir| crate::archive::zip::unpack_archive(zip_archive, output_dir, password, quiet), - output_dir, - &output_file_path, - question_policy, + |output_dir| crate::archive::zip::unpack_archive(zip_archive, output_dir, options.password, options.quiet), + options.output_dir, + &options.output_file_path, + options.question_policy, )? { files } else { @@ -83,15 +85,15 @@ pub fn decompress_file( // about whether the command succeeded without such a message info_accessible(format!( "Successfully decompressed archive in {} ({} files)", - nice_directory_display(output_dir), + nice_directory_display(options.output_dir), files_unpacked )); - if !input_is_stdin && remove { - fs::remove_file(input_file_path)?; + if !input_is_stdin && options.remove { + fs::remove_file(options.input_file_path)?; info(format!( "Removed input file {}", - nice_directory_display(input_file_path) + nice_directory_display(options.input_file_path) )); } @@ -102,7 +104,7 @@ pub fn decompress_file( let reader: Box = if input_is_stdin { Box::new(io::stdin()) } else { - Box::new(fs::File::open(input_file_path)?) + Box::new(fs::File::open(options.input_file_path)?) }; let reader = BufReader::with_capacity(BUFFER_CAPACITY, reader); let mut reader: Box = Box::new(reader); @@ -122,7 +124,7 @@ pub fn decompress_file( Ok(decoder) }; - let (first_extension, extensions) = split_first_compression_format(&formats); + let (first_extension, extensions) = split_first_compression_format(&options.formats); for format in extensions.iter().rev() { reader = chain_reader_decoder(format, reader)?; @@ -132,7 +134,7 @@ pub fn decompress_file( Gzip | Bzip | Bzip3 | Lz4 | Lzma | Snappy | Zstd => { reader = chain_reader_decoder(&first_extension, reader)?; - let mut writer = match utils::ask_to_create_file(&output_file_path, question_policy)? { + let mut writer = match utils::ask_to_create_file(&options.output_file_path, options.question_policy)? { Some(file) => file, None => return Ok(()), }; @@ -143,10 +145,10 @@ pub fn decompress_file( } Tar => { if let ControlFlow::Continue(files) = smart_unpack( - |output_dir| crate::archive::tar::unpack_archive(reader, output_dir, quiet), - output_dir, - &output_file_path, - question_policy, + |output_dir| crate::archive::tar::unpack_archive(reader, output_dir, options.quiet), + options.output_dir, + &options.output_file_path, + options.question_policy, )? { files } else { @@ -154,13 +156,13 @@ pub fn decompress_file( } } Zip => { - if formats.len() > 1 { + if options.formats.len() > 1 { // Locking necessary to guarantee that warning and question // messages stay adjacent let _locks = lock_and_flush_output_stdio(); warn_user_about_loading_zip_in_memory(); - if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? { + if !user_wants_to_continue(options.input_file_path, options.question_policy, QuestionAction::Decompression)? { return Ok(()); } } @@ -170,10 +172,10 @@ pub fn decompress_file( let zip_archive = zip::ZipArchive::new(io::Cursor::new(vec))?; if let ControlFlow::Continue(files) = smart_unpack( - |output_dir| crate::archive::zip::unpack_archive(zip_archive, output_dir, password, quiet), - output_dir, - &output_file_path, - question_policy, + |output_dir| crate::archive::zip::unpack_archive(zip_archive, output_dir, options.password, options.quiet), + options.output_dir, + &options.output_file_path, + options.question_policy, )? { files } else { @@ -183,18 +185,18 @@ pub fn decompress_file( #[cfg(feature = "unrar")] Rar => { type UnpackResult = crate::Result; - let unpack_fn: Box UnpackResult> = if formats.len() > 1 || input_is_stdin { + let unpack_fn: Box UnpackResult> = if options.formats.len() > 1 || input_is_stdin { let mut temp_file = tempfile::NamedTempFile::new()?; io::copy(&mut reader, &mut temp_file)?; Box::new(move |output_dir| { - crate::archive::rar::unpack_archive(temp_file.path(), output_dir, password, quiet) + crate::archive::rar::unpack_archive(temp_file.path(), output_dir, options.password, options.quiet) }) } else { - Box::new(|output_dir| crate::archive::rar::unpack_archive(input_file_path, output_dir, password, quiet)) + Box::new(|output_dir| crate::archive::rar::unpack_archive(options.input_file_path, output_dir, options.password, options.quiet)) }; if let ControlFlow::Continue(files) = - smart_unpack(unpack_fn, output_dir, &output_file_path, question_policy)? + smart_unpack(unpack_fn, options.output_dir, &options.output_file_path, options.question_policy)? { files } else { @@ -206,13 +208,13 @@ pub fn decompress_file( return Err(crate::archive::rar_stub::no_support()); } SevenZip => { - if formats.len() > 1 { + if options.formats.len() > 1 { // Locking necessary to guarantee that warning and question // messages stay adjacent let _locks = lock_and_flush_output_stdio(); warn_user_about_loading_sevenz_in_memory(); - if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? { + if !user_wants_to_continue(options.input_file_path, options.question_policy, QuestionAction::Decompression)? { return Ok(()); } } @@ -222,11 +224,11 @@ pub fn decompress_file( if let ControlFlow::Continue(files) = smart_unpack( |output_dir| { - crate::archive::sevenz::decompress_sevenz(io::Cursor::new(vec), output_dir, password, quiet) + crate::archive::sevenz::decompress_sevenz(io::Cursor::new(vec), output_dir, options.password, options.quiet) }, - output_dir, - &output_file_path, - question_policy, + options.output_dir, + &options.output_file_path, + options.question_policy, )? { files } else { @@ -241,15 +243,15 @@ pub fn decompress_file( // about whether the command succeeded without such a message info_accessible(format!( "Successfully decompressed archive in {}", - nice_directory_display(output_dir) + nice_directory_display(options.output_dir) )); info_accessible(format!("Files unpacked: {}", files_unpacked)); - if !input_is_stdin && remove { - fs::remove_file(input_file_path)?; + if !input_is_stdin && options.remove { + fs::remove_file(options.input_file_path)?; info(format!( "Removed input file {}", - nice_directory_display(input_file_path) + nice_directory_display(options.input_file_path) )); } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index a4b8fca..50f9857 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -7,6 +7,7 @@ mod list; use std::{ops::ControlFlow, path::PathBuf}; use bstr::ByteSlice; +use decompress::DecompressOptions; use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use utils::colors; @@ -193,18 +194,18 @@ pub fn run( path_to_str(file_name), path_to_str(&output_file_path) )); - decompress_file( - input_path, + decompress_file(DecompressOptions { + input_file_path: input_path, formats, - &output_dir, + output_dir: &output_dir, output_file_path, question_policy, - args.quiet, - args.password.as_deref().map(|str| { + quiet: args.quiet, + password: args.password.as_deref().map(|str| { <[u8] as ByteSlice>::from_os_str(str).expect("convert password to bytes failed") }), remove, - ) + }) }) } Subcommand::List { archives: files, tree } => {