Merge branch 'master' into fix-zip-warning

This commit is contained in:
João Marcos Bezerra 2022-03-02 20:32:45 -03:00 committed by GitHub
commit 45a456f127
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 161 additions and 84 deletions

112
Cargo.lock generated
View File

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

View File

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

View File

@ -14,7 +14,7 @@ fn main() {
let out = &Path::new(&env::var_os("OUT_DIR").unwrap()).join("completions"); let out = &Path::new(&env::var_os("OUT_DIR").unwrap()).join("completions");
create_dir_all(out).unwrap(); create_dir_all(out).unwrap();
let app = &mut Opts::into_app(); let app = &mut Opts::command();
for shell in Shell::value_variants() { for shell in Shell::value_variants() {
generate_to(*shell, app, "ouch", out).unwrap(); generate_to(*shell, app, "ouch", out).unwrap();

View File

@ -33,7 +33,9 @@ where
D: Write, D: Write,
{ {
assert!(output_folder.read_dir().expect("dir exists").count() == 0); assert!(output_folder.read_dir().expect("dir exists").count() == 0);
let mut unpacked_files = vec![];
let mut unpacked_files = Vec::with_capacity(archive.len());
for idx in 0..archive.len() { for idx in 0..archive.len() {
let mut file = archive.by_index(idx)?; let mut file = archive.by_index(idx)?;
let file_path = match file.enclosed_name() { let file_path = match file.enclosed_name() {
@ -67,13 +69,15 @@ where
let mut output_file = fs::File::create(&file_path)?; let mut output_file = fs::File::create(&file_path)?;
io::copy(&mut file, &mut output_file)?; io::copy(&mut file, &mut output_file)?;
#[cfg(unix)]
set_last_modified_time(&output_file, &file)?;
} }
} }
#[cfg(unix)] #[cfg(unix)]
__unix_set_permissions(&file_path, &file)?; __unix_set_permissions(&file_path, &file)?;
let file_path = fs::canonicalize(&file_path)?;
unpacked_files.push(file_path); unpacked_files.push(file_path);
} }
@ -204,6 +208,47 @@ fn check_for_comments(file: &ZipFile) {
} }
} }
#[cfg(unix)]
/// Attempts to convert a [`zip::DateTime`] to a [`libc::timespec`].
fn convert_zip_date_time(date_time: zip::DateTime) -> Option<libc::timespec> {
use time::{Date, Month, PrimitiveDateTime, Time};
// Safety: time::Month is repr(u8) and goes from 1 to 12
let month: Month = unsafe { std::mem::transmute(date_time.month()) };
let date = Date::from_calendar_date(date_time.year() as _, month, date_time.day()).ok()?;
let time = Time::from_hms(date_time.hour(), date_time.minute(), date_time.second()).ok()?;
let date_time = PrimitiveDateTime::new(date, time);
let timestamp = date_time.assume_utc().unix_timestamp();
Some(libc::timespec { tv_sec: timestamp, tv_nsec: 0 })
}
#[cfg(unix)]
fn set_last_modified_time(file: &fs::File, zip_file: &ZipFile) -> crate::Result<()> {
use std::os::unix::prelude::AsRawFd;
use libc::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);
// The first value is the last accessed time, which we'll set as being right now.
// The second value is the last modified time, which we'll copy over from the zip archive
let times = [now, last_modified];
let output_fd = file.as_raw_fd();
// TODO: check for -1
unsafe { libc::futimens(output_fd, &times as *const _) };
Ok(())
}
#[cfg(unix)] #[cfg(unix)]
fn __unix_set_permissions(file_path: &Path, file: &ZipFile) -> crate::Result<()> { fn __unix_set_permissions(file_path: &Path, file: &ZipFile) -> crate::Result<()> {
use std::{fs::Permissions, os::unix::fs::PermissionsExt}; use std::{fs::Permissions, os::unix::fs::PermissionsExt};

View File

@ -89,16 +89,16 @@ pub fn run(
// To file.tar.bz.xz // To file.tar.bz.xz
let extensions_text: String = formats.iter().map(|format| format.to_string()).collect(); let extensions_text: String = formats.iter().map(|format| format.to_string()).collect();
let output_path = to_utf(output_path); let output_path = to_utf(&output_path).to_string();
// Breaks if Lzma is .lz or .lzma and not .xz // Breaks if Lzma is .lz or .lzma and not .xz
// Or if Bzip is .bz2 and not .bz // Or if Bzip is .bz2 and not .bz
let extensions_start_position = output_path.rfind(&extensions_text).unwrap(); let extensions_start_position = output_path.rfind(&extensions_text).unwrap();
let pos = extensions_start_position - 1; let pos = extensions_start_position - 1;
let mut suggested_output_path = output_path.clone(); let mut suggested_output_path = output_path.to_string();
suggested_output_path.insert_str(pos, ".tar"); suggested_output_path.insert_str(pos, ".tar");
let error = FinalError::with_title(format!("Cannot compress to '{}'.", to_utf(&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.")
@ -127,7 +127,7 @@ pub fn run(
let output_file = fs::File::create(&output_path)?; let output_file = fs::File::create(&output_path)?;
if !represents_several_files(&files) { 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` // `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]); let input_extensions = extension::extensions_from_path(&files[0]);
@ -161,7 +161,7 @@ pub fn run(
info!( info!(
accessible, // important information accessible, // important information
"Partial compression detected. Compressing {} into {}", "Partial compression detected. Compressing {} into {}",
to_utf(files[0].as_path().file_name().unwrap()), to_utf(files[0].as_path().file_name().unwrap().as_ref()),
to_utf(&output_path) to_utf(&output_path)
); );
formats = new_formats; formats = new_formats;
@ -175,7 +175,7 @@ pub fn run(
// 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 compressed '{}'.", to_utf(output_path)); info!(accessible, "Successfully compressed '{}'.", to_utf(&output_path));
} else { } else {
// If Ok(false) or Err() occurred, delete incomplete file // If Ok(false) or Err() occurred, delete incomplete file
// Print an extra alert message pointing out that we left a possibly // Print an extra alert message pointing out that we left a possibly
@ -702,8 +702,8 @@ fn smart_unpack(
info!( info!(
accessible, accessible,
"Successfully moved {} to {}.", "Successfully moved {} to {}.",
nice_directory_display(&temp_dir_path), nice_directory_display(temp_dir_path),
nice_directory_display(&output_file_path) nice_directory_display(output_file_path)
); );
} }
Ok(ControlFlow::Continue(files)) Ok(ControlFlow::Continue(files))

View File

@ -1,13 +1,20 @@
use std::{borrow::Cow, cmp, ffi::OsStr, path::Path}; use std::{borrow::Cow, cmp, path::Path};
// The lifetimes here could elided but I think they help
// comprehension in this case
#[allow(clippy::needless_lifetimes)]
/// Converts an OsStr to utf8 with custom formatting. /// Converts an OsStr to utf8 with custom formatting.
/// ///
/// This is different from [`Path::display`]. /// This is different from [`Path::display`].
/// ///
/// See <https://gist.github.com/marcospb19/ebce5572be26397cf08bbd0fd3b65ac1> for a comparison. /// See <https://gist.github.com/marcospb19/ebce5572be26397cf08bbd0fd3b65ac1> for a comparison.
pub fn to_utf(os_str: impl AsRef<OsStr>) -> String { pub fn to_utf<'a>(os_str: &'a Path) -> Cow<'a, str> {
let text = format!("{:?}", os_str.as_ref()); let format = || {
text.trim_matches('"').to_string() let text = format!("{:?}", os_str);
Cow::Owned(text.trim_matches('"').to_string())
};
os_str.to_str().map_or_else(format, Cow::Borrowed)
} }
/// Removes the current dir from the beginning of a path /// Removes the current dir from the beginning of a path
@ -21,25 +28,27 @@ pub fn strip_cur_dir(source_path: &Path) -> &Path {
/// Converts a slice of AsRef<OsStr> to comma separated String /// Converts a slice of AsRef<OsStr> to comma separated String
/// ///
/// Panics if the slice is empty. /// Panics if the slice is empty.
pub fn concatenate_os_str_list(os_strs: &[impl AsRef<OsStr>]) -> String { pub fn concatenate_os_str_list(os_strs: &[impl AsRef<Path>]) -> String {
let mut iter = os_strs.iter().map(AsRef::as_ref); let mut iter = os_strs.iter().map(AsRef::as_ref);
let mut string = to_utf(iter.next().unwrap()); // May panic let mut string = to_utf(iter.next().unwrap()).to_string(); // May panic
for os_str in iter { for os_str in iter {
string += ", "; string += ", ";
string += &to_utf(os_str); string += &*to_utf(os_str);
} }
string string
} }
// The lifetimes here could elided but I think they help
// comprehension in this case
#[allow(clippy::needless_lifetimes)]
/// Display the directory name, but change to "current directory" when necessary. /// Display the directory name, but change to "current directory" when necessary.
pub fn nice_directory_display(os_str: impl AsRef<OsStr>) -> Cow<'static, str> { pub fn nice_directory_display<'a>(path: &'a Path) -> Cow<'a, str> {
if os_str.as_ref() == "." { if path == Path::new(".") {
Cow::Borrowed("current directory") Cow::Borrowed("current directory")
} else { } else {
let text = to_utf(os_str); to_utf(path)
Cow::Owned(format!("'{}'", text))
} }
} }

View File

@ -44,7 +44,7 @@ pub fn user_wants_to_overwrite(path: &Path, question_policy: QuestionPolicy) ->
QuestionPolicy::AlwaysNo => Ok(false), QuestionPolicy::AlwaysNo => Ok(false),
QuestionPolicy::Ask => { QuestionPolicy::Ask => {
let path = to_utf(strip_cur_dir(path)); let path = to_utf(strip_cur_dir(path));
let path = Some(path.as_str()); let path = Some(&*path);
let placeholder = Some("FILE"); let placeholder = Some("FILE");
Confirmation::new("Do you want to overwrite 'FILE'?", placeholder).ask(path) Confirmation::new("Do you want to overwrite 'FILE'?", placeholder).ask(path)
} }
@ -87,7 +87,7 @@ pub fn user_wants_to_continue(
QuestionAction::Decompression => "decompressing", QuestionAction::Decompression => "decompressing",
}; };
let path = to_utf(strip_cur_dir(path)); let path = to_utf(strip_cur_dir(path));
let path = Some(path.as_str()); let path = Some(&*path);
let placeholder = Some("FILE"); let placeholder = Some("FILE");
Confirmation::new(&format!("Do you want to continue {} 'FILE'?", action), placeholder).ask(path) Confirmation::new(&format!("Do you want to continue {} 'FILE'?", action), placeholder).ask(path)
} }