From a26d3d34ce8a22174c3f7e57850c8d77e506bbd7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20M=2E=20Bezerra?= Date: Sat, 16 Sep 2023 13:44:45 -0300 Subject: [PATCH] Improve hints when decompressing with no extension refactored `check_missing_formats_when_decompressing` to be aware of missing extensions and unsupported extensions in order to give a more detailed error message --- src/check.rs | 55 +++++++++++++++------- src/extension.rs | 15 +++--- ...ui_test_err_decompress_missing_extension-2.snap | 12 +++++ ...ui_test_err_decompress_missing_extension-3.snap | 14 ++++++ ...__ui_test_err_decompress_missing_extension.snap | 28 +++++------ tests/ui.rs | 4 +- 6 files changed, 89 insertions(+), 39 deletions(-) create mode 100644 tests/snapshots/ui__ui_test_err_decompress_missing_extension-2.snap create mode 100644 tests/snapshots/ui__ui_test_err_decompress_missing_extension-3.snap rewrite tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap (69%) diff --git a/src/check.rs b/src/check.rs index 62d97c5..9e1bdac 100644 --- a/src/check.rs +++ b/src/check.rs @@ -10,7 +10,7 @@ use std::{ use crate::{ error::FinalError, - extension::{build_archive_file_suggestion, Extension}, + extension::{build_archive_file_suggestion, Extension, PRETTY_SUPPORTED_ALIASES, PRETTY_SUPPORTED_EXTENSIONS}, info, utils::{pretty_format_list_of_paths, try_infer_extension, user_wants_to_continue, EscapedPathDisplay}, warning, QuestionAction, QuestionPolicy, Result, @@ -127,32 +127,55 @@ pub fn check_archive_formats_position(formats: &[Extension], output_path: &Path) /// Check if all provided files have formats to decompress. pub fn check_missing_formats_when_decompressing(files: &[PathBuf], formats: &[Vec]) -> Result<()> { - let files_missing_format: Vec = files + let files_with_broken_extension: Vec<&PathBuf> = files .iter() .zip(formats) .filter(|(_, format)| format.is_empty()) - .map(|(input_path, _)| PathBuf::from(input_path)) + .map(|(input_path, _)| input_path) .collect(); - if let Some(path) = files_missing_format.first() { - let error = FinalError::with_title("Cannot decompress files without extensions") - .detail(format!( - "Files without supported extensions: {}", - pretty_format_list_of_paths(&files_missing_format) - )) - .detail("Decompression formats are detected automatically by the file extension") - .hint("Provide a file with a supported extension:") - .hint(" ouch decompress example.tar.gz") + if files_with_broken_extension.is_empty() { + return Ok(()); + } + + let (files_with_unsupported_extensions, files_missing_extension): (Vec<&PathBuf>, Vec<&PathBuf>) = + files_with_broken_extension + .iter() + .partition(|path| path.extension().is_some()); + + let mut error = FinalError::with_title("Cannot decompress files"); + + if !files_with_unsupported_extensions.is_empty() { + error = error.detail(format!( + "Files with unsupported extensions: {}", + pretty_format_list_of_paths(&files_with_unsupported_extensions) + )); + } + + if !files_missing_extension.is_empty() { + error = error.detail(format!( + "Files with missing extensions: {}", + pretty_format_list_of_paths(&files_missing_extension) + )); + } + + error = error + .detail("Decompression formats are detected automatically from file extension") + .hint(format!("Supported extensions are: {}", PRETTY_SUPPORTED_EXTENSIONS)) + .hint(format!("Supported aliases are: {}", PRETTY_SUPPORTED_ALIASES)); + + // If there's exactly one file, give a suggestion to use `--format` + if let &[path] = files_with_broken_extension.as_slice() { + error = error .hint("") - .hint("Or overwrite this option with the '--format' flag:") + .hint("Alternatively, you can pass an extension to the '--format' flag:") .hint(format!( " ouch decompress {} --format tar.gz", EscapedPathDisplay::new(path), )); - - return Err(error.into()); } - Ok(()) + + Err(error.into()) } /// Check if there is a first format when compressing, and returns it. diff --git a/src/extension.rs b/src/extension.rs index 016da7d..ac79303 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -7,6 +7,11 @@ use bstr::ByteSlice; use self::CompressionFormat::*; use crate::{error::Error, warning}; +pub const SUPPORTED_EXTENSIONS: &[&str] = &["tar", "zip", "bz", "bz2", "gz", "lz4", "xz", "lzma", "sz", "zst"]; +pub const SUPPORTED_ALIASES: &[&str] = &["tgz", "tbz", "tlz4", "txz", "tzlma", "tsz", "tzst"]; +pub const PRETTY_SUPPORTED_EXTENSIONS: &str = "tar, zip, bz, bz2, gz, lz4, xz, lzma, sz, zst"; +pub const PRETTY_SUPPORTED_ALIASES: &str = "tgz, tbz, tlz4, txz, tzlma, tsz, tzst"; + /// A wrapper around `CompressionFormat` that allows combinations like `tgz` #[derive(Debug, Clone, Eq)] #[non_exhaustive] @@ -85,11 +90,6 @@ impl CompressionFormat { } } -pub const SUPPORTED_EXTENSIONS: &[&str] = &[ - "tar", "tgz", "tbz", "tlz4", "txz", "tzlma", "tsz", "tzst", "zip", "bz", "bz2", "gz", "lz4", "xz", "lzma", "sz", - "zst", -]; - fn to_extension(ext: &[u8]) -> Option { Some(Extension::new( match ext { @@ -156,7 +156,7 @@ pub fn separate_known_extensions_from_name(path: &Path) -> (&Path, Vec // If the extension we got is a supported extension, generate the suggestion // at the position we found - if SUPPORTED_EXTENSIONS.contains(&maybe_extension) { + if SUPPORTED_EXTENSIONS.contains(&maybe_extension) || SUPPORTED_ALIASES.contains(&maybe_extension) { let mut path = path.to_string(); path.insert_str(position_to_insert - 1, suggested_extension); @@ -227,7 +227,6 @@ mod tests { #[test] fn test_extensions_from_path() { - use CompressionFormat::*; let path = Path::new("bolovo.tar.gz"); let extensions: Vec = extensions_from_path(path); diff --git a/tests/snapshots/ui__ui_test_err_decompress_missing_extension-2.snap b/tests/snapshots/ui__ui_test_err_decompress_missing_extension-2.snap new file mode 100644 index 0000000..5f5cddb --- /dev/null +++ b/tests/snapshots/ui__ui_test_err_decompress_missing_extension-2.snap @@ -0,0 +1,12 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch decompress a b.unknown\", dir)" +--- +[ERROR] Cannot decompress files + - Files with unsupported extensions: /b.unknown + - Files with missing extensions: /a + - Decompression formats are detected automatically from file extension + +hint: Supported extensions are: tar, zip, bz, bz2, gz, lz4, xz, lzma, sz, zst +hint: Supported aliases are: tgz, tbz, tlz4, txz, tzlma, tsz, tzst + diff --git a/tests/snapshots/ui__ui_test_err_decompress_missing_extension-3.snap b/tests/snapshots/ui__ui_test_err_decompress_missing_extension-3.snap new file mode 100644 index 0000000..1fd4ab8 --- /dev/null +++ b/tests/snapshots/ui__ui_test_err_decompress_missing_extension-3.snap @@ -0,0 +1,14 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch decompress b.unknown\", dir)" +--- +[ERROR] Cannot decompress files + - Files with unsupported extensions: /b.unknown + - Decompression formats are detected automatically from file extension + +hint: Supported extensions are: tar, zip, bz, bz2, gz, lz4, xz, lzma, sz, zst +hint: Supported aliases are: tgz, tbz, tlz4, txz, tzlma, tsz, tzst +hint: +hint: Alternatively, you can pass an extension to the '--format' flag: +hint: ouch decompress /b.unknown --format tar.gz + diff --git a/tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap b/tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap dissimilarity index 69% index b5ae330..9850d48 100644 --- a/tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap +++ b/tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap @@ -1,14 +1,14 @@ ---- -source: tests/ui.rs -expression: "run_ouch(\"ouch decompress a\", dir)" ---- -[ERROR] Cannot decompress files without extensions - - Files without supported extensions: /a - - Decompression formats are detected automatically by the file extension - -hint: Provide a file with a supported extension: -hint: ouch decompress example.tar.gz -hint: -hint: Or overwrite this option with the '--format' flag: -hint: ouch decompress /a --format tar.gz - +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch decompress a\", dir)" +--- +[ERROR] Cannot decompress files + - Files with missing extensions: /a + - Decompression formats are detected automatically from file extension + +hint: Supported extensions are: tar, zip, bz, bz2, gz, lz4, xz, lzma, sz, zst +hint: Supported aliases are: tgz, tbz, tlz4, txz, tzlma, tsz, tzst +hint: +hint: Alternatively, you can pass an extension to the '--format' flag: +hint: ouch decompress /a --format tar.gz + diff --git a/tests/ui.rs b/tests/ui.rs index efbf8c1..c72f052 100644 --- a/tests/ui.rs +++ b/tests/ui.rs @@ -71,9 +71,11 @@ fn ui_test_err_compress_missing_extension() { fn ui_test_err_decompress_missing_extension() { let (_dropper, dir) = testdir().unwrap(); - run_in(dir, "touch", "a").unwrap(); + run_in(dir, "touch", "a b.unknown").unwrap(); ui!(run_ouch("ouch decompress a", dir)); + ui!(run_ouch("ouch decompress a b.unknown", dir)); + ui!(run_ouch("ouch decompress b.unknown", dir)); } #[test] -- 2.11.4.GIT