From 14025c681618b85e59b1b118bd020c84547ece23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20M=2E=20Bezerra?= Date: Sat, 4 Jun 2022 13:06:22 -0300 Subject: [PATCH] remove `use_small_heuristics = "Max"` from rustfmt and update edition to 2021 --- rustfmt.toml | 3 +- src/archive/zip.rs | 15 ++++++-- src/commands/compress.rs | 22 ++++++++--- src/commands/decompress.rs | 32 +++++++++++---- src/commands/mod.rs | 75 +++++++++++++++++++++++++++++------- src/error.rs | 38 ++++++++++++++---- src/extension.rs | 43 +++++++++++++-------- src/list.rs | 4 +- src/progress.rs | 9 ++++- src/utils/file_visibility.rs | 17 ++++++-- src/utils/fs.rs | 4 +- src/utils/mod.rs | 5 ++- src/utils/question.rs | 23 +++++++++-- tests/integration.rs | 15 ++++++-- tests/mime.rs | 5 ++- 15 files changed, 239 insertions(+), 71 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index a3badd9..8a9367d 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,11 +2,10 @@ max_width = 120 use_field_init_shorthand = true newline_style = "Unix" -edition = "2018" +edition = "2021" reorder_imports = true reorder_modules = true use_try_shorthand = true -use_small_heuristics = "Max" # Unstable features (nightly only) unstable_features = true diff --git a/src/archive/zip.rs b/src/archive/zip.rs index 183e6a4..c0bdf48 100644 --- a/src/archive/zip.rs +++ b/src/archive/zip.rs @@ -144,7 +144,10 @@ where if !invalid_unicode_filenames.is_empty() { let error = FinalError::with_title("Cannot build zip archive") .detail("Zip archives require files to have valid UTF-8 paths") - .detail(format!("Files with invalid paths: {}", concatenate_os_str_list(&invalid_unicode_filenames))); + .detail(format!( + "Files with invalid paths: {}", + concatenate_os_str_list(&invalid_unicode_filenames) + )); return Err(error.into()); } @@ -223,7 +226,10 @@ fn convert_zip_date_time(date_time: zip::DateTime) -> Option { let date_time = PrimitiveDateTime::new(date, time); let timestamp = date_time.assume_utc().unix_timestamp(); - Some(libc::timespec { tv_sec: timestamp, tv_nsec: 0 }) + Some(libc::timespec { + tv_sec: timestamp, + tv_nsec: 0, + }) } #[cfg(unix)] @@ -232,7 +238,10 @@ fn set_last_modified_time(file: &fs::File, zip_file: &ZipFile) -> crate::Result< use libc::UTIME_NOW; - let now = libc::timespec { tv_sec: 0, tv_nsec: UTIME_NOW }; + let now = libc::timespec { + tv_sec: 0, + tv_nsec: UTIME_NOW, + }; let last_modified = zip_file.last_modified(); let last_modified = convert_zip_date_time(last_modified).unwrap_or(now); diff --git a/src/commands/compress.rs b/src/commands/compress.rs index 4186996..0f141bc 100644 --- a/src/commands/compress.rs +++ b/src/commands/compress.rs @@ -38,7 +38,9 @@ pub fn compress_files( let (total_input_size, precise) = files .iter() .map(|f| (f.metadata().expect("file exists").len(), f.is_file())) - .fold((0, true), |(total_size, and_precise), (size, precise)| (total_size + size, and_precise & precise)); + .fold((0, true), |(total_size, and_precise), (size, precise)| { + (total_size + size, and_precise & precise) + }); // NOTE: canonicalize is here to avoid a weird bug: // > If output_file_path is a nested path and it exists and the user overwrite it @@ -81,7 +83,9 @@ pub fn compress_files( let _progress = Progress::new_accessible_aware( total_input_size, precise, - Some(Box::new(move || output_file_path.metadata().expect("file exists").len())), + Some(Box::new(move || { + output_file_path.metadata().expect("file exists").len() + })), ); writer = chain_writer_encoder(&first_extension, writer)?; @@ -92,14 +96,19 @@ pub fn compress_files( let mut progress = Progress::new_accessible_aware( total_input_size, precise, - Some(Box::new(move || output_file_path.metadata().expect("file exists").len())), + Some(Box::new(move || { + output_file_path.metadata().expect("file exists").len() + })), ); archive::tar::build_archive_from_paths( &files, &mut writer, file_visibility_policy, - progress.as_mut().map(Progress::display_handle).unwrap_or(&mut io::stdout()), + progress + .as_mut() + .map(Progress::display_handle) + .unwrap_or(&mut io::stdout()), )?; writer.flush()?; } @@ -134,7 +143,10 @@ pub fn compress_files( &files, &mut vec_buffer, file_visibility_policy, - progress.as_mut().map(Progress::display_handle).unwrap_or(&mut io::stdout()), + progress + .as_mut() + .map(Progress::display_handle) + .unwrap_or(&mut io::stdout()), )?; let vec_buffer = vec_buffer.into_inner(); io::copy(&mut vec_buffer.as_slice(), &mut writer)?; diff --git a/src/commands/decompress.rs b/src/commands/decompress.rs index 8cff065..f18ffe9 100644 --- a/src/commands/decompress.rs +++ b/src/commands/decompress.rs @@ -43,7 +43,11 @@ pub fn decompress_file( // in-memory decompression/copying first. // // Any other Zip decompression done can take up the whole RAM and freeze ouch. - if let [Extension { compression_formats: [Zip], .. }] = formats.as_slice() { + if let [Extension { + compression_formats: [Zip], + .. + }] = formats.as_slice() + { let zip_archive = zip::ZipArchive::new(reader)?; let files = if let ControlFlow::Continue(files) = smart_unpack( Box::new(move |output_dir| { @@ -51,7 +55,10 @@ pub fn decompress_file( crate::archive::zip::unpack_archive( zip_archive, output_dir, - progress.as_mut().map(Progress::display_handle).unwrap_or(&mut io::stdout()), + progress + .as_mut() + .map(Progress::display_handle) + .unwrap_or(&mut io::stdout()), ) }), output_dir, @@ -128,7 +135,10 @@ pub fn decompress_file( crate::archive::tar::unpack_archive( reader, output_dir, - progress.as_mut().map(Progress::display_handle).unwrap_or(&mut io::stdout()), + progress + .as_mut() + .map(Progress::display_handle) + .unwrap_or(&mut io::stdout()), ) }), output_dir, @@ -160,7 +170,10 @@ pub fn decompress_file( crate::archive::zip::unpack_archive( zip_archive, output_dir, - progress.as_mut().map(Progress::display_handle).unwrap_or(&mut io::stdout()), + progress + .as_mut() + .map(Progress::display_handle) + .unwrap_or(&mut io::stdout()), ) }), output_dir, @@ -178,7 +191,11 @@ pub fn decompress_file( // having a final status message is important especially in an accessibility context // as screen readers may not read a commands exit code, making it hard to reason // about whether the command succeeded without such a message - info!(accessible, "Successfully decompressed archive in {}.", nice_directory_display(output_dir)); + info!( + accessible, + "Successfully decompressed archive in {}.", + nice_directory_display(output_dir) + ); info!(accessible, "Files unpacked: {}", files_unpacked.len()); Ok(()) @@ -211,8 +228,9 @@ fn smart_unpack( // Only one file in the root directory, so we can just move it to the output directory let file = fs::read_dir(&temp_dir_path)?.next().expect("item exists")?; let file_path = file.path(); - let file_name = - file_path.file_name().expect("Should be safe because paths in archives should not end with '..'"); + let file_name = file_path + .file_name() + .expect("Should be safe because paths in archives should not end with '..'"); let correct_path = output_dir.join(file_name); // One case to handle tough is we need to check if a file with the same name already exists if !utils::clear_path(&correct_path, question_policy)? { diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 790d370..ce971d5 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -74,7 +74,10 @@ pub fn run( file_visibility_policy: FileVisibilityPolicy, ) -> crate::Result<()> { match args.cmd { - Subcommand::Compress { mut files, output: output_path } => { + Subcommand::Compress { + mut files, + output: output_path, + } => { // If the output_path file exists and is the same as some of the input files, warn the user and skip those inputs (in order to avoid compression recursion) if output_path.exists() { deduplicate_input_files(&mut files, &fs::canonicalize(&output_path)?); @@ -95,7 +98,10 @@ pub fn run( .hint(format!(" ouch compress ... {}.zip", to_utf(&output_path))) .hint("") .hint("Alternatively, you can overwrite this option by using the '--format' flag:") - .hint(format!(" ouch compress ... {} --format tar.gz", to_utf(&output_path))); + .hint(format!( + " ouch compress ... {} --format tar.gz", + to_utf(&output_path) + )); return Err(error.into()); } @@ -118,7 +124,10 @@ pub fn run( let error = FinalError::with_title(format!("Cannot compress to '{}'.", output_path)) .detail("You are trying to compress multiple files.") - .detail(format!("The compression format '{}' cannot receive multiple files.", &formats[0])) + .detail(format!( + "The compression format '{}' cannot receive multiple files.", + &formats[0] + )) .detail("The only supported formats that archive files into an archive are .tar and .zip.") .hint(format!("Try inserting '.tar' or '.zip' before '{}'.", &formats[0])) .hint(format!("From: {}", output_path)) @@ -130,9 +139,19 @@ pub fn run( if let Some(format) = formats.iter().skip(1).find(|format| format.is_archive()) { let error = FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&output_path))) .detail(format!("Found the format '{}' in an incorrect position.", format)) - .detail(format!("'{}' can only be used at the start of the file extension.", format)) - .hint(format!("If you wish to compress multiple files, start the extension with '{}'.", format)) - .hint(format!("Otherwise, remove the last '{}' from '{}'.", format, to_utf(&output_path))); + .detail(format!( + "'{}' can only be used at the start of the file extension.", + format + )) + .hint(format!( + "If you wish to compress multiple files, start the extension with '{}'.", + format + )) + .hint(format!( + "Otherwise, remove the last '{}' from '{}'.", + format, + to_utf(&output_path) + )); return Err(error.into()); } @@ -185,8 +204,14 @@ pub fn run( formats = new_formats; } } - let compress_result = - compress_files(files, formats, output_file, &output_path, question_policy, file_visibility_policy); + let compress_result = compress_files( + files, + formats, + output_file, + &output_path, + question_policy, + file_visibility_policy, + ); if let Ok(true) = compress_result { // this is only printed once, so it doesn't result in much text. On the other hand, @@ -201,8 +226,16 @@ pub fn run( if let Err(err) = fs::remove_file(&output_path) { eprintln!("{red}FATAL ERROR:\n", red = *colors::RED); eprintln!(" Please manually delete '{}'.", to_utf(&output_path)); - eprintln!(" Compression failed and we could not delete '{}'.", to_utf(&output_path),); - eprintln!(" Error:{reset} {}{red}.{reset}\n", err, reset = *colors::RESET, red = *colors::RED); + eprintln!( + " Compression failed and we could not delete '{}'.", + to_utf(&output_path), + ); + eprintln!( + " Error:{reset} {}{red}.{reset}\n", + err, + reset = *colors::RESET, + red = *colors::RED + ); } } @@ -240,7 +273,10 @@ pub fn run( .hint(" ouch decompress example.tar.gz") .hint("") .hint("Or overwrite this option with the '--format' flag:") - .hint(format!(" ouch decompress {} --format tar.gz", to_utf(&files_missing_format[0]))); + .hint(format!( + " ouch decompress {} --format tar.gz", + to_utf(&files_missing_format[0]) + )); return Err(error.into()); } @@ -285,7 +321,10 @@ pub fn run( if !not_archives.is_empty() { let error = FinalError::with_title("Cannot list archive contents") .detail("Only archives can have their contents listed") - .detail(format!("Files are not archives: {}", concatenate_os_str_list(¬_archives))); + .detail(format!( + "Files are not archives: {}", + concatenate_os_str_list(¬_archives) + )); return Err(error.into()); } @@ -316,7 +355,12 @@ fn check_mime_type( if let Some(detected_format) = try_infer_extension(path) { // Infering the file extension can have unpredicted consequences (e.g. the user just // mistyped, ...) which we should always inform the user about. - info!(accessible, "Detected file: `{}` extension as `{}`", path.display(), detected_format); + info!( + accessible, + "Detected file: `{}` extension as `{}`", + path.display(), + detected_format + ); if user_wants_to_continue(path, question_policy, QuestionAction::Decompression)? { format.push(detected_format); } else { @@ -350,7 +394,10 @@ fn deduplicate_input_files(files: &mut Vec, output_path: &Path) { let mut idx = 0; while idx < files.len() { if files[idx] == output_path { - warning!("The output file and the input file are the same: `{}`, skipping...", output_path.display()); + warning!( + "The output file and the input file are the same: `{}`, skipping...", + output_path.display() + ); files.remove(idx); } else { idx += 1; diff --git a/src/error.rs b/src/error.rs index 63685b5..81ac85d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -94,7 +94,11 @@ impl FinalError { /// Only constructor #[must_use] pub fn with_title(title: impl Into) -> Self { - Self { title: title.into(), details: vec![], hints: vec![] } + Self { + title: title.into(), + details: vec![], + hints: vec![], + } } /// Add one detail line, can have multiple @@ -142,17 +146,35 @@ impl fmt::Display for Error { impl From for Error { fn from(err: std::io::Error) -> Self { match err.kind() { - std::io::ErrorKind::NotFound => Self::NotFound { error_title: err.to_string() }, - std::io::ErrorKind::PermissionDenied => Self::PermissionDenied { error_title: err.to_string() }, - std::io::ErrorKind::AlreadyExists => Self::AlreadyExists { error_title: err.to_string() }, - _other => Self::IoError { reason: err.to_string() }, + std::io::ErrorKind::NotFound => { + Self::NotFound { + error_title: err.to_string(), + } + } + std::io::ErrorKind::PermissionDenied => { + Self::PermissionDenied { + error_title: err.to_string(), + } + } + std::io::ErrorKind::AlreadyExists => { + Self::AlreadyExists { + error_title: err.to_string(), + } + } + _other => { + Self::IoError { + reason: err.to_string(), + } + } } } } impl From for Error { fn from(err: lzzzz::lz4f::Error) -> Self { - Self::Lz4Error { reason: err.to_string() } + Self::Lz4Error { + reason: err.to_string(), + } } } @@ -174,7 +196,9 @@ impl From for Error { impl From for Error { fn from(err: ignore::Error) -> Self { - Self::WalkdirError { reason: err.to_string() } + Self::WalkdirError { + reason: err.to_string(), + } } } diff --git a/src/extension.rs b/src/extension.rs index 92c255d..8995eef 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -25,7 +25,10 @@ impl Extension { /// Will panic if `formats` is empty pub fn new(formats: &'static [CompressionFormat], text: impl ToString) -> Self { assert!(!formats.is_empty()); - Self { compression_formats: formats, display_text: text.to_string() } + Self { + compression_formats: formats, + display_text: text.to_string(), + } } /// Checks if the first format in `compression_formats` is an archive @@ -80,20 +83,18 @@ impl CompressionFormat { impl fmt::Display for CompressionFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - match self { - Gzip => ".gz", - Bzip => ".bz", - Zstd => ".zst", - Lz4 => ".lz4", - Lzma => ".lz", - Snappy => ".sz", - Tar => ".tar", - Zip => ".zip", - } - ) + let text = match self { + Gzip => ".gz", + Bzip => ".bz", + Zstd => ".zst", + Lz4 => ".lz4", + Lzma => ".lz", + Snappy => ".sz", + Tar => ".tar", + Zip => ".zip", + }; + + write!(f, "{text}") } } @@ -137,7 +138,11 @@ pub fn separate_known_extensions_from_name(mut path: &Path) -> (&Path, Vec (CompressionForm } pub fn flatten_compression_formats(extensions: &[Extension]) -> Vec { - extensions.iter().flat_map(|extension| extension.compression_formats.iter()).copied().collect() + extensions + .iter() + .flat_map(|extension| extension.compression_formats.iter()) + .copied() + .collect() } diff --git a/src/list.rs b/src/list.rs index c8bd8ab..ab6d836 100644 --- a/src/list.rs +++ b/src/list.rs @@ -47,7 +47,9 @@ pub fn list_files( .map(|file| { let file = file?; if !crate::cli::ACCESSIBLE.get().unwrap() { - pb.as_ref().expect("exists").set_message(format!("Processing: {}", file.path.display())); + pb.as_ref() + .expect("exists") + .set_message(format!("Processing: {}", file.path.display())); } Ok(file) }) diff --git a/src/progress.rs b/src/progress.rs index 02dbcd3..b61cec5 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -36,7 +36,9 @@ impl io::Write for DisplayHandle { fn io_error(_: X) -> io::Error { io::Error::new(io::ErrorKind::Other, "failed to flush buffer") } - self.sender.send(String::from_utf8(self.buf.drain(..).collect()).map_err(io_error)?).map_err(io_error) + self.sender + .send(String::from_utf8(self.buf.drain(..).collect()).map_err(io_error)?) + .map_err(io_error) } } @@ -99,7 +101,10 @@ impl Progress { Progress { draw_stop: draw_tx, clean_done: clean_rx, - display_handle: DisplayHandle { buf: Vec::new(), sender: msg_tx }, + display_handle: DisplayHandle { + buf: Vec::new(), + sender: msg_tx, + }, } } diff --git a/src/utils/file_visibility.rs b/src/utils/file_visibility.rs index f0570bc..d8abd40 100644 --- a/src/utils/file_visibility.rs +++ b/src/utils/file_visibility.rs @@ -23,7 +23,12 @@ pub struct FileVisibilityPolicy { impl Default for FileVisibilityPolicy { fn default() -> Self { - Self { read_ignore: false, read_hidden: true, read_git_ignore: false, read_git_exclude: false } + Self { + read_ignore: false, + read_hidden: true, + read_git_ignore: false, + read_git_exclude: false, + } } } @@ -41,13 +46,19 @@ impl FileVisibilityPolicy { #[must_use] /// Enables reading .gitignore files. pub fn read_git_ignore(self, read_git_ignore: bool) -> Self { - Self { read_git_ignore, ..self } + Self { + read_git_ignore, + ..self + } } #[must_use] /// Enables reading `.git/info/exclude` files. pub fn read_git_exclude(self, read_git_exclude: bool) -> Self { - Self { read_git_exclude, ..self } + Self { + read_git_exclude, + ..self + } } #[must_use] diff --git a/src/utils/fs.rs b/src/utils/fs.rs index ae94097..ec321bd 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -129,5 +129,7 @@ pub fn try_infer_extension(path: &Path) -> Option { /// This is the same as the nightly https://doc.rust-lang.org/std/path/struct.Path.html#method.is_symlink // Useful to detect broken symlinks when compressing. (So we can safely ignore them) pub fn is_symlink(path: &Path) -> bool { - fs::symlink_metadata(path).map(|m| m.file_type().is_symlink()).unwrap_or(false) + fs::symlink_metadata(path) + .map(|m| m.file_type().is_symlink()) + .unwrap_or(false) } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 78fb2a9..e30037b 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -29,6 +29,9 @@ mod utf8 { /// Filter out list of paths that are not utf8 valid pub fn get_invalid_utf8_paths(paths: &[PathBuf]) -> Vec<&PathBuf> { - paths.iter().filter_map(|path| is_invalid_utf8(path).then(|| path)).collect() + paths + .iter() + .filter_map(|path| is_invalid_utf8(path).then(|| path)) + .collect() } } diff --git a/src/utils/question.rs b/src/utils/question.rs index 13ef5b6..a15c660 100644 --- a/src/utils/question.rs +++ b/src/utils/question.rs @@ -110,7 +110,10 @@ pub struct Confirmation<'a> { impl<'a> Confirmation<'a> { /// Creates a new Confirmation. pub const fn new(prompt: &'a str, pattern: Option<&'a str>) -> Self { - Self { prompt, placeholder: pattern } + Self { + prompt, + placeholder: pattern, + } } /// Creates user message and receives a boolean input to be used on the program @@ -124,9 +127,23 @@ impl<'a> Confirmation<'a> { // Ask the same question to end while no valid answers are given loop { if *crate::cli::ACCESSIBLE.get().unwrap() { - print!("{} {}yes{}/{}no{}: ", message, *colors::GREEN, *colors::RESET, *colors::RED, *colors::RESET); + print!( + "{} {}yes{}/{}no{}: ", + message, + *colors::GREEN, + *colors::RESET, + *colors::RED, + *colors::RESET + ); } else { - print!("{} [{}Y{}/{}n{}] ", message, *colors::GREEN, *colors::RESET, *colors::RED, *colors::RESET); + print!( + "{} [{}Y{}/{}n{}] ", + message, + *colors::GREEN, + *colors::RESET, + *colors::RED, + *colors::RESET + ); } io::stdout().flush()?; diff --git a/tests/integration.rs b/tests/integration.rs index 6112825..eec7a29 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -51,7 +51,10 @@ enum Extension { // converts a list of extension structs to string fn merge_extensions(ext: impl ToString, exts: Vec) -> String { - once(ext.to_string()).chain(exts.into_iter().map(|x| x.to_string())).collect::>().join(".") + once(ext.to_string()) + .chain(exts.into_iter().map(|x| x.to_string())) + .collect::>() + .join(".") } // create random nested directories and files under the specified directory @@ -64,7 +67,10 @@ fn create_random_files(dir: impl Into, depth: u8, rng: &mut SmallRng) { // create 0 to 7 random files for _ in 0..rng.gen_range(0..8u32) { - write_random_content(&mut tempfile::Builder::new().tempfile_in(dir).unwrap().keep().unwrap().0, rng); + write_random_content( + &mut tempfile::Builder::new().tempfile_in(dir).unwrap().keep().unwrap().0, + rng, + ); } // create more random files in 0 to 3 new directories @@ -83,7 +89,10 @@ fn single_empty_file(ext: Extension, #[any(size_range(0..8).lift())] exts: Vec