Merge branch 'master' into override-completions-target

This commit is contained in:
João Marcos Bezerra 2022-03-20 12:40:08 -03:00 committed by GitHub
commit 890d89a96f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 100 deletions

92
Cargo.lock generated
View File

@ -44,9 +44,9 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bit-set"
@ -109,18 +109,18 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.72"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
dependencies = [
"jobserver",
]
[[package]]
name = "cfb"
version = "0.4.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca453e8624711b2f0f4eb47076a318feda166252a827ee25d067b43de83dcba0"
checksum = "74f89d248799e3f15f91b70917f65381062a01bb8e222700ea0e5a7ff9785f9c"
dependencies = [
"byteorder",
"uuid",
@ -134,9 +134,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "3.0.7"
version = "3.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12e8611f9ae4e068fa3e56931fded356ff745e70987ff76924a6e0ab1c8ef2e3"
checksum = "86f8c0e2a6b902acc18214e24a6935cdaf8a8e34231913d4404dcaee659f65a1"
dependencies = [
"atty",
"bitflags",
@ -151,18 +151,18 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "3.0.4"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d044e9db8cd0f68191becdeb5246b7462e4cf0c069b19ae00d1bf3fa9889498d"
checksum = "23eec4dd324308f49d8bf86a2732078c34d57955fec1e1d865554fc37c15d420"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
version = "3.0.6"
version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153"
checksum = "01d42c94ce7c2252681b5fed4d3627cc807b13dfc033246bd05d5b252399000e"
dependencies = [
"heck",
"proc-macro-error",
@ -186,18 +186,18 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.3.0"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.6"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120"
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
dependencies = [
"cfg-if",
"lazy_static",
@ -229,9 +229,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "fastrand"
version = "1.6.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
@ -269,15 +269,15 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fs-err"
version = "2.6.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ebd3504ad6116843b8375ad70df74e7bfe83cac77a1f3fe73200c844d43bfe0"
checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e"
[[package]]
name = "getrandom"
version = "0.2.4"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
dependencies = [
"cfg-if",
"libc",
@ -360,9 +360,9 @@ dependencies = [
[[package]]
name = "infer"
version = "0.5.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea70330449622910e0edebab230734569516269fb32342fb0a8956340fa48c6c"
checksum = "20b2b533137b9cad970793453d4f921c2e91312a6d88b1085c07bc15fc51bb3b"
dependencies = [
"cfb",
]
@ -402,9 +402,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.112"
version = "0.2.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
[[package]]
name = "libz-sys"
@ -445,9 +445,9 @@ dependencies = [
[[package]]
name = "lzzzz"
version = "0.8.0"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6d891cedd3b1659c206a60ff8afd15bccd7c2754b157f8a164861989e042b88"
checksum = "e8be9301236955fb2b31545b8d4be8b28b8057cd5fbfa30dfef899e5c64b7079"
dependencies = [
"cc",
]
@ -540,9 +540,9 @@ dependencies = [
[[package]]
name = "parse-display"
version = "0.5.3"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "898bf4c2a569dedbfd4e6c3f0bbd0ae825e5b6b0b69bae3e3c1000158689334a"
checksum = "8bb10034e2db1d7ec22c3da90743505c07ab1e7483e93df8222c41dadb5937e8"
dependencies = [
"once_cell",
"parse-display-derive",
@ -551,9 +551,9 @@ dependencies = [
[[package]]
name = "parse-display-derive"
version = "0.5.3"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1779d1e28ab04568223744c2af4aa4e642e67b92c76bdce0929a6d2c36267199"
checksum = "4546f47b5e547d7f9a5cc60d798798aebb013bb930df9297ada0048fd4901558"
dependencies = [
"once_cell",
"proc-macro2",
@ -670,18 +670,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quote"
version = "1.0.14"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
@ -815,9 +815,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.85"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [
"proc-macro2",
"quote",
@ -914,9 +914,9 @@ dependencies = [
[[package]]
name = "thread_local"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
dependencies = [
"once_cell",
]
@ -1044,18 +1044,18 @@ dependencies = [
[[package]]
name = "zstd"
version = "0.9.2+zstd.1.5.1"
version = "0.10.0+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54"
checksum = "3b1365becbe415f3f0fcd024e2f7b45bacfb5bdd055f0dc113571394114e7bdd"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "4.1.3+zstd.1.5.1"
version = "4.1.4+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79"
checksum = "2f7cd17c9af1a4d6c24beb1cc54b17e2ef7b593dc92f19e9d9acad8b182bbaee"
dependencies = [
"libc",
"zstd-sys",
@ -1063,9 +1063,9 @@ dependencies = [
[[package]]
name = "zstd-sys"
version = "1.6.2+zstd.1.5.1"
version = "1.6.3+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f"
checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8"
dependencies = [
"cc",
"libc",

View File

@ -15,19 +15,19 @@ description = "A command-line utility for easily compressing and decompressing f
[dependencies]
atty = "0.2.14"
bzip2 = "0.4.3"
clap = { version = "3.0.4", features = ["derive", "env"] }
clap = { version = "3.1.3", features = ["derive", "env"] }
flate2 = { version = "1.0.22", default-features = false }
fs-err = "2.6.0"
libc = "0.2.103"
fs-err = "2.7.0"
libc = "0.2.119"
linked-hash-map = "0.5.4"
lzzzz = "0.8.0"
once_cell = "1.8.0"
lzzzz = "1.0.2"
once_cell = "1.9.0"
snap = "1.0.5"
tar = "0.4.37"
tar = "0.4.38"
xz2 = "0.1.6"
zip = { version = "0.5.13", default-features = false }
zstd = { version = "0.9.0", default-features = false }
tempfile = "3.2.0"
zstd = { version = "0.10.0", default-features = false }
tempfile = "3.3.0"
ignore = "0.4.18"
indicatif = "0.16.2"
@ -35,15 +35,15 @@ indicatif = "0.16.2"
time = { version = "0.3.7", default-features = false }
[build-dependencies]
clap = { version = "3.0.4", features = ["derive", "env"] }
clap_complete = "3.0.2"
clap = { version = "3.1.3", features = ["derive", "env"] }
clap_complete = "3.1.0"
[dev-dependencies]
assert_cmd = "2.0.2"
infer = "0.5.0"
parse-display = "0.5.3"
assert_cmd = "2.0.4"
infer = "0.7.0"
parse-display = "0.5.4"
proptest = "1.0.0"
rand = { version = "0.8.3", default-features = false, features = ["small_rng", "std"] }
rand = { version = "0.8.5", default-features = false, features = ["small_rng", "std"] }
test-strategy = "0.1.2"
[features]

View File

@ -45,7 +45,7 @@ fn main() {
if let Some(completions_output_directory) = detect_completions_output_directory() {
create_dir_all(&completions_output_directory).expect("Could not create shell completions output folder.");
let app = &mut Opts::into_app();
let app = &mut Opts::command();
for shell in Shell::value_variants() {
generate_to(*shell, app, "ouch", &completions_output_directory)

View File

@ -29,6 +29,13 @@ use crate::{
warning, Opts, QuestionAction, QuestionPolicy, Subcommand,
};
// Message used to advice the user that .zip archives have limitations that require it to load everything into memory at once
// and this can lead to out-of-memory scenarios for archives that are big enough.
const ZIP_IN_MEMORY_LIMITATION_WARNING: &str =
"\tThere is a limitation for .zip archives with extra extensions. (e.g. <file>.zip.gz)
\tThe design of .zip makes it impossible to compress via stream, so it must be done entirely in memory.
\tBy compressing .zip with extra compression formats, you can run out of RAM if the file is too large!";
// Used in BufReader and BufWriter to perform less syscalls
const BUFFER_CAPACITY: usize = 1024 * 64;
@ -120,7 +127,7 @@ pub fn run(
let output_file = fs::File::create(&output_path)?;
if !represents_several_files(&files) {
// It's possible the file is already partially compressed so we don't want to compress it again
// It is possible the file is already partially compressed so we don't want to compress it again
// `ouch compress file.tar.gz file.tar.gz.xz` should produce `file.tar.gz.xz` and not `file.tar.gz.tar.gz.xz`
let input_extensions = extension::extensions_from_path(&files[0]);
@ -163,8 +170,14 @@ pub fn run(
let compress_result =
compress_files(files, formats, output_file, &output_path, question_policy, file_visibility_policy);
// If any error occurred, delete incomplete file
if compress_result.is_err() {
if let Ok(true) = compress_result {
// this is only printed once, so it doesn't result in much text. On the other hand,
// 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 compressed '{}'.", to_utf(&output_path));
} else {
// If Ok(false) or Err() occurred, delete incomplete file
// Print an extra alert message pointing out that we left a possibly
// CORRUPTED FILE at `output_path`
if let Err(err) = fs::remove_file(&output_path) {
@ -173,12 +186,6 @@ pub fn run(
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);
}
} else {
// this is only printed once, so it doesn't result in much text. On the other hand,
// 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 compressed '{}'.", to_utf(&output_path));
}
compress_result?;
@ -284,6 +291,8 @@ pub fn run(
// files are the list of paths to be compressed: ["dir/file1.txt", "dir/file2.txt"]
// formats contains each format necessary for compression, example: [Tar, Gz] (in compression order)
// output_file is the resulting compressed file name, example: "compressed.tar.gz"
//
// Returns Ok(true) if compressed all files successfully, and Ok(false) if user opted to skip files
fn compress_files(
files: Vec<PathBuf>,
formats: Vec<Extension>,
@ -291,14 +300,15 @@ fn compress_files(
output_dir: &Path,
question_policy: QuestionPolicy,
file_visibility_policy: FileVisibilityPolicy,
) -> crate::Result<()> {
) -> crate::Result<bool> {
// The next lines are for displaying the progress bar
// If the input files contain a directory, then the total size will be underestimated
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));
//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
// >> output_file_path.exists() will always return false (somehow)
// - canonicalize seems to fix this
@ -360,16 +370,14 @@ fn compress_files(
writer.flush()?;
}
Zip => {
eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET);
eprintln!(
"\tThere is a limitation for .zip archives with extra extensions. (e.g. <file>.zip.gz)\
\n\tThe design of .zip makes it impossible to compress via stream, so it must be done entirely in memory.\
\n\tBy compressing .zip with extra compression formats, you can run out of RAM if the file is too large!"
);
if formats.len() > 1 {
eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET);
eprintln!("{}", ZIP_IN_MEMORY_LIMITATION_WARNING);
// give user the option to continue compressing after warning is shown
if !user_wants_to_continue(output_dir, question_policy, QuestionAction::Compression)? {
return Ok(());
// give user the option to continue compressing after warning is shown
if !user_wants_to_continue(output_dir, question_policy, QuestionAction::Compression)? {
return Ok(false);
}
}
let mut vec_buffer = io::Cursor::new(vec![]);
@ -400,7 +408,7 @@ fn compress_files(
}
}
Ok(())
Ok(true)
}
// Decompress a file
@ -523,16 +531,14 @@ fn decompress_file(
};
}
Zip => {
eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET);
eprintln!(
"\tThere is a limitation for .zip archives with extra extensions. (e.g. <file>.zip.gz)\
\n\tThe design of .zip makes it impossible to compress via stream, so it must be done entirely in memory.\
\n\tBy compressing .zip with extra compression formats, you can run out of RAM if the file is too large!"
);
if formats.len() > 1 {
eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET);
eprintln!("{}", ZIP_IN_MEMORY_LIMITATION_WARNING);
// give user the option to continue decompressing after warning is shown
if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? {
return Ok(());
// give user the option to continue decompressing after warning is shown
if !user_wants_to_continue(input_file_path, question_policy, QuestionAction::Decompression)? {
return Ok(());
}
}
let mut vec = vec![];
@ -620,16 +626,14 @@ fn list_archive_contents(
let files: Box<dyn Iterator<Item = crate::Result<FileInArchive>>> = match formats[0] {
Tar => Box::new(crate::archive::tar::list_archive(tar::Archive::new(reader))),
Zip => {
eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET);
eprintln!(
"\tThere is a limitation for .zip archives with extra extensions. (e.g. <file>.zip.gz)\
\n\tThe design of .zip makes it impossible to compress via stream, so it must be done entirely in memory.\
\n\tBy compressing .zip with extra compression formats, you can run out of RAM if the file is too large!"
);
if formats.len() > 1 {
eprintln!("{orange}[WARNING]{reset}", orange = *colors::ORANGE, reset = *colors::RESET);
eprintln!("{}", ZIP_IN_MEMORY_LIMITATION_WARNING);
// give user the option to continue decompressing after warning is shown
if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? {
return Ok(());
// give user the option to continue decompressing after warning is shown
if !user_wants_to_continue(archive_path, question_policy, QuestionAction::Decompression)? {
return Ok(());
}
}
let mut vec = vec![];