remove use_small_heuristics = "Max" from rustfmt

and update edition to 2021
This commit is contained in:
João M. Bezerra 2022-06-04 13:06:22 -03:00
parent f5fcf7f2a3
commit 14025c6816
15 changed files with 239 additions and 71 deletions

View File

@ -2,11 +2,10 @@
max_width = 120 max_width = 120
use_field_init_shorthand = true use_field_init_shorthand = true
newline_style = "Unix" newline_style = "Unix"
edition = "2018" edition = "2021"
reorder_imports = true reorder_imports = true
reorder_modules = true reorder_modules = true
use_try_shorthand = true use_try_shorthand = true
use_small_heuristics = "Max"
# Unstable features (nightly only) # Unstable features (nightly only)
unstable_features = true unstable_features = true

View File

@ -144,7 +144,10 @@ where
if !invalid_unicode_filenames.is_empty() { if !invalid_unicode_filenames.is_empty() {
let error = FinalError::with_title("Cannot build zip archive") let error = FinalError::with_title("Cannot build zip archive")
.detail("Zip archives require files to have valid UTF-8 paths") .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()); return Err(error.into());
} }
@ -223,7 +226,10 @@ fn convert_zip_date_time(date_time: zip::DateTime) -> Option<libc::timespec> {
let date_time = PrimitiveDateTime::new(date, time); let date_time = PrimitiveDateTime::new(date, time);
let timestamp = date_time.assume_utc().unix_timestamp(); 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)] #[cfg(unix)]
@ -232,7 +238,10 @@ fn set_last_modified_time(file: &fs::File, zip_file: &ZipFile) -> crate::Result<
use libc::UTIME_NOW; 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 = zip_file.last_modified();
let last_modified = convert_zip_date_time(last_modified).unwrap_or(now); let last_modified = convert_zip_date_time(last_modified).unwrap_or(now);

View File

@ -38,7 +38,9 @@ pub fn compress_files(
let (total_input_size, precise) = files let (total_input_size, precise) = files
.iter() .iter()
.map(|f| (f.metadata().expect("file exists").len(), f.is_file())) .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: // 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 // > 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( let _progress = Progress::new_accessible_aware(
total_input_size, total_input_size,
precise, 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)?; writer = chain_writer_encoder(&first_extension, writer)?;
@ -92,14 +96,19 @@ pub fn compress_files(
let mut progress = Progress::new_accessible_aware( let mut progress = Progress::new_accessible_aware(
total_input_size, total_input_size,
precise, 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( archive::tar::build_archive_from_paths(
&files, &files,
&mut writer, &mut writer,
file_visibility_policy, 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()?; writer.flush()?;
} }
@ -134,7 +143,10 @@ pub fn compress_files(
&files, &files,
&mut vec_buffer, &mut vec_buffer,
file_visibility_policy, 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(); let vec_buffer = vec_buffer.into_inner();
io::copy(&mut vec_buffer.as_slice(), &mut writer)?; io::copy(&mut vec_buffer.as_slice(), &mut writer)?;

View File

@ -43,7 +43,11 @@ pub fn decompress_file(
// in-memory decompression/copying first. // in-memory decompression/copying first.
// //
// Any other Zip decompression done can take up the whole RAM and freeze ouch. // 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 zip_archive = zip::ZipArchive::new(reader)?;
let files = if let ControlFlow::Continue(files) = smart_unpack( let files = if let ControlFlow::Continue(files) = smart_unpack(
Box::new(move |output_dir| { Box::new(move |output_dir| {
@ -51,7 +55,10 @@ pub fn decompress_file(
crate::archive::zip::unpack_archive( crate::archive::zip::unpack_archive(
zip_archive, zip_archive,
output_dir, 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, output_dir,
@ -128,7 +135,10 @@ pub fn decompress_file(
crate::archive::tar::unpack_archive( crate::archive::tar::unpack_archive(
reader, reader,
output_dir, 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, output_dir,
@ -160,7 +170,10 @@ pub fn decompress_file(
crate::archive::zip::unpack_archive( crate::archive::zip::unpack_archive(
zip_archive, zip_archive,
output_dir, 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, output_dir,
@ -178,7 +191,11 @@ pub fn decompress_file(
// having a final status message is important especially in an accessibility context // 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 // as screen readers may not read a commands exit code, making it hard to reason
// about whether the command succeeded without such a message // 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()); info!(accessible, "Files unpacked: {}", files_unpacked.len());
Ok(()) 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 // 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 = fs::read_dir(&temp_dir_path)?.next().expect("item exists")?;
let file_path = file.path(); let file_path = file.path();
let file_name = let file_name = file_path
file_path.file_name().expect("Should be safe because paths in archives should not end with '..'"); .file_name()
.expect("Should be safe because paths in archives should not end with '..'");
let correct_path = output_dir.join(file_name); 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 // 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)? { if !utils::clear_path(&correct_path, question_policy)? {

View File

@ -74,7 +74,10 @@ pub fn run(
file_visibility_policy: FileVisibilityPolicy, file_visibility_policy: FileVisibilityPolicy,
) -> crate::Result<()> { ) -> crate::Result<()> {
match args.cmd { 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 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() { if output_path.exists() {
deduplicate_input_files(&mut files, &fs::canonicalize(&output_path)?); deduplicate_input_files(&mut files, &fs::canonicalize(&output_path)?);
@ -95,7 +98,10 @@ pub fn run(
.hint(format!(" ouch compress <FILES>... {}.zip", to_utf(&output_path))) .hint(format!(" ouch compress <FILES>... {}.zip", to_utf(&output_path)))
.hint("") .hint("")
.hint("Alternatively, you can overwrite this option by using the '--format' flag:") .hint("Alternatively, you can overwrite this option by using the '--format' flag:")
.hint(format!(" ouch compress <FILES>... {} --format tar.gz", to_utf(&output_path))); .hint(format!(
" ouch compress <FILES>... {} --format tar.gz",
to_utf(&output_path)
));
return Err(error.into()); return Err(error.into());
} }
@ -118,7 +124,10 @@ pub fn run(
let error = FinalError::with_title(format!("Cannot compress to '{}'.", output_path)) let error = FinalError::with_title(format!("Cannot compress to '{}'.", output_path))
.detail("You are trying to compress multiple files.") .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.") .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!("Try inserting '.tar' or '.zip' before '{}'.", &formats[0]))
.hint(format!("From: {}", output_path)) .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()) { 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))) 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!("Found the format '{}' in an incorrect position.", format))
.detail(format!("'{}' can only be used at the start of the file extension.", format)) .detail(format!(
.hint(format!("If you wish to compress multiple files, start the extension with '{}'.", format)) "'{}' can only be used at the start of the file extension.",
.hint(format!("Otherwise, remove the last '{}' from '{}'.", format, to_utf(&output_path))); 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()); return Err(error.into());
} }
@ -185,8 +204,14 @@ pub fn run(
formats = new_formats; formats = new_formats;
} }
} }
let compress_result = let compress_result = compress_files(
compress_files(files, formats, output_file, &output_path, question_policy, file_visibility_policy); files,
formats,
output_file,
&output_path,
question_policy,
file_visibility_policy,
);
if let Ok(true) = compress_result { if let Ok(true) = compress_result {
// this is only printed once, so it doesn't result in much text. On the other hand, // 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) { if let Err(err) = fs::remove_file(&output_path) {
eprintln!("{red}FATAL ERROR:\n", red = *colors::RED); eprintln!("{red}FATAL ERROR:\n", red = *colors::RED);
eprintln!(" Please manually delete '{}'.", to_utf(&output_path)); eprintln!(" Please manually delete '{}'.", to_utf(&output_path));
eprintln!(" Compression failed and we could not delete '{}'.", to_utf(&output_path),); eprintln!(
eprintln!(" Error:{reset} {}{red}.{reset}\n", err, reset = *colors::RESET, red = *colors::RED); " 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(" ouch decompress example.tar.gz")
.hint("") .hint("")
.hint("Or overwrite this option with the '--format' flag:") .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()); return Err(error.into());
} }
@ -285,7 +321,10 @@ pub fn run(
if !not_archives.is_empty() { if !not_archives.is_empty() {
let error = FinalError::with_title("Cannot list archive contents") let error = FinalError::with_title("Cannot list archive contents")
.detail("Only archives can have their contents listed") .detail("Only archives can have their contents listed")
.detail(format!("Files are not archives: {}", concatenate_os_str_list(&not_archives))); .detail(format!(
"Files are not archives: {}",
concatenate_os_str_list(&not_archives)
));
return Err(error.into()); return Err(error.into());
} }
@ -316,7 +355,12 @@ fn check_mime_type(
if let Some(detected_format) = try_infer_extension(path) { if let Some(detected_format) = try_infer_extension(path) {
// Infering the file extension can have unpredicted consequences (e.g. the user just // Infering the file extension can have unpredicted consequences (e.g. the user just
// mistyped, ...) which we should always inform the user about. // 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)? { if user_wants_to_continue(path, question_policy, QuestionAction::Decompression)? {
format.push(detected_format); format.push(detected_format);
} else { } else {
@ -350,7 +394,10 @@ fn deduplicate_input_files(files: &mut Vec<PathBuf>, output_path: &Path) {
let mut idx = 0; let mut idx = 0;
while idx < files.len() { while idx < files.len() {
if files[idx] == output_path { 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); files.remove(idx);
} else { } else {
idx += 1; idx += 1;

View File

@ -94,7 +94,11 @@ impl FinalError {
/// Only constructor /// Only constructor
#[must_use] #[must_use]
pub fn with_title(title: impl Into<CowStr>) -> Self { pub fn with_title(title: impl Into<CowStr>) -> Self {
Self { title: title.into(), details: vec![], hints: vec![] } Self {
title: title.into(),
details: vec![],
hints: vec![],
}
} }
/// Add one detail line, can have multiple /// Add one detail line, can have multiple
@ -142,17 +146,35 @@ impl fmt::Display for Error {
impl From<std::io::Error> for Error { impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self { fn from(err: std::io::Error) -> Self {
match err.kind() { match err.kind() {
std::io::ErrorKind::NotFound => Self::NotFound { error_title: err.to_string() }, std::io::ErrorKind::NotFound => {
std::io::ErrorKind::PermissionDenied => Self::PermissionDenied { error_title: err.to_string() }, Self::NotFound {
std::io::ErrorKind::AlreadyExists => Self::AlreadyExists { error_title: err.to_string() }, error_title: err.to_string(),
_other => Self::IoError { reason: 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<lzzzz::lz4f::Error> for Error { impl From<lzzzz::lz4f::Error> for Error {
fn from(err: lzzzz::lz4f::Error) -> Self { 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<zip::result::ZipError> for Error {
impl From<ignore::Error> for Error { impl From<ignore::Error> for Error {
fn from(err: ignore::Error) -> Self { fn from(err: ignore::Error) -> Self {
Self::WalkdirError { reason: err.to_string() } Self::WalkdirError {
reason: err.to_string(),
}
} }
} }

View File

@ -25,7 +25,10 @@ impl Extension {
/// Will panic if `formats` is empty /// Will panic if `formats` is empty
pub fn new(formats: &'static [CompressionFormat], text: impl ToString) -> Self { pub fn new(formats: &'static [CompressionFormat], text: impl ToString) -> Self {
assert!(!formats.is_empty()); 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 /// Checks if the first format in `compression_formats` is an archive
@ -80,10 +83,7 @@ impl CompressionFormat {
impl fmt::Display for CompressionFormat { impl fmt::Display for CompressionFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( let text = match self {
f,
"{}",
match self {
Gzip => ".gz", Gzip => ".gz",
Bzip => ".bz", Bzip => ".bz",
Zstd => ".zst", Zstd => ".zst",
@ -92,8 +92,9 @@ impl fmt::Display for CompressionFormat {
Snappy => ".sz", Snappy => ".sz",
Tar => ".tar", Tar => ".tar",
Zip => ".zip", Zip => ".zip",
} };
)
write!(f, "{text}")
} }
} }
@ -137,7 +138,11 @@ pub fn separate_known_extensions_from_name(mut path: &Path) -> (&Path, Vec<Exten
extensions.push(extension); extensions.push(extension);
// Update for the next iteration // Update for the next iteration
path = if let Some(stem) = path.file_stem() { Path::new(stem) } else { Path::new("") }; path = if let Some(stem) = path.file_stem() {
Path::new(stem)
} else {
Path::new("")
};
} }
// Put the extensions in the correct order: left to right // Put the extensions in the correct order: left to right
extensions.reverse(); extensions.reverse();
@ -175,5 +180,9 @@ pub fn split_first_compression_format(formats: &[Extension]) -> (CompressionForm
} }
pub fn flatten_compression_formats(extensions: &[Extension]) -> Vec<CompressionFormat> { pub fn flatten_compression_formats(extensions: &[Extension]) -> Vec<CompressionFormat> {
extensions.iter().flat_map(|extension| extension.compression_formats.iter()).copied().collect() extensions
.iter()
.flat_map(|extension| extension.compression_formats.iter())
.copied()
.collect()
} }

View File

@ -47,7 +47,9 @@ pub fn list_files(
.map(|file| { .map(|file| {
let file = file?; let file = file?;
if !crate::cli::ACCESSIBLE.get().unwrap() { 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) Ok(file)
}) })

View File

@ -36,7 +36,9 @@ impl io::Write for DisplayHandle {
fn io_error<X>(_: X) -> io::Error { fn io_error<X>(_: X) -> io::Error {
io::Error::new(io::ErrorKind::Other, "failed to flush buffer") 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 { Progress {
draw_stop: draw_tx, draw_stop: draw_tx,
clean_done: clean_rx, clean_done: clean_rx,
display_handle: DisplayHandle { buf: Vec::new(), sender: msg_tx }, display_handle: DisplayHandle {
buf: Vec::new(),
sender: msg_tx,
},
} }
} }

View File

@ -23,7 +23,12 @@ pub struct FileVisibilityPolicy {
impl Default for FileVisibilityPolicy { impl Default for FileVisibilityPolicy {
fn default() -> Self { 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] #[must_use]
/// Enables reading .gitignore files. /// Enables reading .gitignore files.
pub fn read_git_ignore(self, read_git_ignore: bool) -> Self { pub fn read_git_ignore(self, read_git_ignore: bool) -> Self {
Self { read_git_ignore, ..self } Self {
read_git_ignore,
..self
}
} }
#[must_use] #[must_use]
/// Enables reading `.git/info/exclude` files. /// Enables reading `.git/info/exclude` files.
pub fn read_git_exclude(self, read_git_exclude: bool) -> Self { pub fn read_git_exclude(self, read_git_exclude: bool) -> Self {
Self { read_git_exclude, ..self } Self {
read_git_exclude,
..self
}
} }
#[must_use] #[must_use]

View File

@ -129,5 +129,7 @@ pub fn try_infer_extension(path: &Path) -> Option<Extension> {
/// This is the same as the nightly https://doc.rust-lang.org/std/path/struct.Path.html#method.is_symlink /// 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) // Useful to detect broken symlinks when compressing. (So we can safely ignore them)
pub fn is_symlink(path: &Path) -> bool { 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)
} }

View File

@ -29,6 +29,9 @@ mod utf8 {
/// Filter out list of paths that are not utf8 valid /// Filter out list of paths that are not utf8 valid
pub fn get_invalid_utf8_paths(paths: &[PathBuf]) -> Vec<&PathBuf> { 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()
} }
} }

View File

@ -110,7 +110,10 @@ pub struct Confirmation<'a> {
impl<'a> Confirmation<'a> { impl<'a> Confirmation<'a> {
/// Creates a new Confirmation. /// Creates a new Confirmation.
pub const fn new(prompt: &'a str, pattern: Option<&'a str>) -> Self { 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 /// 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 // Ask the same question to end while no valid answers are given
loop { loop {
if *crate::cli::ACCESSIBLE.get().unwrap() { 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 { } 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()?; io::stdout().flush()?;

View File

@ -51,7 +51,10 @@ enum Extension {
// converts a list of extension structs to string // converts a list of extension structs to string
fn merge_extensions(ext: impl ToString, exts: Vec<FileExtension>) -> String { fn merge_extensions(ext: impl ToString, exts: Vec<FileExtension>) -> String {
once(ext.to_string()).chain(exts.into_iter().map(|x| x.to_string())).collect::<Vec<_>>().join(".") once(ext.to_string())
.chain(exts.into_iter().map(|x| x.to_string()))
.collect::<Vec<_>>()
.join(".")
} }
// create random nested directories and files under the specified directory // create random nested directories and files under the specified directory
@ -64,7 +67,10 @@ fn create_random_files(dir: impl Into<PathBuf>, depth: u8, rng: &mut SmallRng) {
// create 0 to 7 random files // create 0 to 7 random files
for _ in 0..rng.gen_range(0..8u32) { 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 // 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<F
let before_file = &before.join("file"); let before_file = &before.join("file");
let archive = &dir.join(format!("file.{}", merge_extensions(ext, exts))); let archive = &dir.join(format!("file.{}", merge_extensions(ext, exts)));
let after = &dir.join("after"); let after = &dir.join("after");
write_random_content(&mut fs::File::create(before_file).unwrap(), &mut SmallRng::from_entropy()); write_random_content(
&mut fs::File::create(before_file).unwrap(),
&mut SmallRng::from_entropy(),
);
ouch!("-A", "c", before_file, archive); ouch!("-A", "c", before_file, archive);
ouch!("-A", "d", archive, "-d", after); ouch!("-A", "d", archive, "-d", after);
assert_same_directory(before, after, false); assert_same_directory(before, after, false);

View File

@ -46,8 +46,9 @@ fn sanity_check_through_mime() {
let compressed_file_path = &format!("{}.{}", path_to_compress.display(), format); let compressed_file_path = &format!("{}.{}", path_to_compress.display(), format);
ouch!("c", path_to_compress, compressed_file_path); ouch!("c", path_to_compress, compressed_file_path);
let sniffed = let sniffed = infer::get_from_path(compressed_file_path)
infer::get_from_path(compressed_file_path).expect("the file to be read").expect("the MIME to be found"); .expect("the file to be read")
.expect("the MIME to be found");
assert_eq!(&sniffed.mime_type(), expected_mime); assert_eq!(&sniffed.mime_type(), expected_mime);
} }