Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ouch for openSUSE:Factory checked in 
at 2023-01-07 17:19:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ouch (Old)
 and      /work/SRC/openSUSE:Factory/.ouch.new.1563 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ouch"

Sat Jan  7 17:19:52 2023 rev:4 rq:1056759 version:0.4.1~0

Changes:
--------
--- /work/SRC/openSUSE:Factory/ouch/ouch.changes        2022-12-01 
17:22:21.546605963 +0100
+++ /work/SRC/openSUSE:Factory/.ouch.new.1563/ouch.changes      2023-01-07 
17:23:14.971421358 +0100
@@ -1,0 +2,21 @@
+Sat Jan  7 11:39:00 UTC 2023 - Michael Vetter <mvet...@suse.com>
+
+- Update to 0.4.1:
+  New Features:
+  * Add cli option to (de)compress quietly #325
+  Improvements:
+  * Allow ouch to decompress archive into existing folder #321
+  * Accept inserting subcommand-independent flags in any position #329
+  * Improve extension parsing logic #330
+  * Slight refactor when ensuring archive-only inputs #331
+  * Use BStr to display possibly non-UTF8 byte sequences#332
+  * Use ubyte instead of humansize #333 #333
+  * Stop keeping track of the names of unpacked files #334
+  * Clean up #335
+  Bug fixes:
+  * Stop incorrectly asking to remove the parent dir #321
+  * Fixed overwriting archive file when decompressing archive detected with 
MIME types.
+  Tweaks:
+  * Add scoop install instructions to readme #323
+
+-------------------------------------------------------------------

Old:
----
  ouch-0.4.0~0.tar.xz

New:
----
  ouch-0.4.1~0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ouch.spec ++++++
--- /var/tmp/diff_new_pack.5qfvOe/_old  2023-01-07 17:23:16.027427658 +0100
+++ /var/tmp/diff_new_pack.5qfvOe/_new  2023-01-07 17:23:16.031427682 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package ouch
 #
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           ouch
-Version:        0.4.0~0
+Version:        0.4.1~0
 Release:        0
 Summary:        Compression and decompression utility for the terminal
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.5qfvOe/_old  2023-01-07 17:23:16.067427896 +0100
+++ /var/tmp/diff_new_pack.5qfvOe/_new  2023-01-07 17:23:16.071427920 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/ouch-org/ouch.git</param>
     <param name="versionformat">@PARENT_TAG@~@TAG_OFFSET@</param>
     <param name="scm">git</param>
-    <param name="revision">0.4.0</param>
+    <param name="revision">0.4.1</param>
     <param name="match-tag">*</param>
     <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param>
     <param name="versionrewrite-replacement">\1</param>

++++++ ouch-0.4.0~0.tar.xz -> ouch-0.4.1~0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/CHANGELOG.md 
new/ouch-0.4.1~0/CHANGELOG.md
--- old/ouch-0.4.0~0/CHANGELOG.md       2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/CHANGELOG.md       2023-01-05 23:15:43.000000000 +0100
@@ -18,9 +18,32 @@
 
 **Bullet points in chronological order by PR**
 
-## [Unreleased](https://github.com/ouch-org/ouch/compare/0.4.0...HEAD)
+## [Unreleased](https://github.com/ouch-org/ouch/compare/0.4.1...HEAD)
 
-This is currently empty.
+## [0.4.1](https://github.com/ouch-org/ouch/compare/0.4.0...0.4.1)
+
+### New Features
+
+- Add cli option to (de)compress quietly 
[\#325](https://github.com/ouch-org/ouch/pull/325) 
([a-moreira](https://github.com/a-moreira))
+
+### Improvements
+
+- Allow ouch to decompress archive into existing folder 
[\#321](https://github.com/ouch-org/ouch/pull/321) 
([a-moreira](https://github.com/a-moreira))
+- Accept inserting subcommand-independent flags in any position 
[\#329](https://github.com/ouch-org/ouch/pull/329) 
([marcospb19](https://github.com/marcospb19))
+- Improve extension parsing logic 
[\#330](https://github.com/ouch-org/ouch/pull/330) 
([figsoda](https://github.com/figsoda))
+- Slight refactor when ensuring archive-only inputs 
[\#331](https://github.com/ouch-org/ouch/pull/331) 
([vrmiguel](https://github.com/vrmiguel))
+- Use BStr to display possibly non-UTF8 byte 
sequences[\#332](https://github.com/ouch-org/ouch/pull/332) 
([vrmiguel](https://github.com/vrmiguel))
+- Use ubyte instead of humansize #333  
[\#333](https://github.com/ouch-org/ouch/pull/333) 
([vrmiguel](https://github.com/vrmiguel))
+- Stop keeping track of the names of unpacked files  
[\#334](https://github.com/ouch-org/ouch/pull/334) 
([vrmiguel](https://github.com/vrmiguel))
+- Clean up [\#335](https://github.com/ouch-org/ouch/pull/335) 
([figsoda](https://github.com/figsoda))
+
+### Bug fixes
+
+- Stop incorrectly asking to remove the parent dir 
[\#321](https://github.com/ouch-org/ouch/pull/321) 
([a-moreira](https://github.com/a-moreira))
+
+### Tweaks
+
+- Add scoop install instructions to readme 
[\#323](https://github.com/ouch-org/ouch/pull/323) 
([rasa](https://github.com/rasa))
 
 ## [0.4.0](https://github.com/ouch-org/ouch/compare/0.3.1...0.4.0) (2022-11-20)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/Cargo.lock new/ouch-0.4.1~0/Cargo.lock
--- old/ouch-0.4.0~0/Cargo.lock 2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/Cargo.lock 2023-01-05 23:15:43.000000000 +0100
@@ -19,11 +19,11 @@
 
 [[package]]
 name = "assert_cmd"
-version = "2.0.6"
+version = "2.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "ba45b8163c49ab5f972e59a8a5a03b6d2972619d486e19ec9fe744f7c2753d3c"
+checksum = "fa3d466004a8b4cb1bc34044240a2fd29d17607e2e3bd613eb44fd48e8100da3"
 dependencies = [
- "bstr 1.0.1",
+ "bstr 1.1.0",
  "doc-comment",
  "predicates",
  "predicates-core",
@@ -37,7 +37,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
  "winapi",
 ]
@@ -80,9 +80,9 @@
 
 [[package]]
 name = "bstr"
-version = "1.0.1"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd"
+checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
 dependencies = [
  "memchr",
  "once_cell",
@@ -119,9 +119,9 @@
 
 [[package]]
 name = "cc"
-version = "1.0.77"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
+checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
 dependencies = [
  "jobserver",
 ]
@@ -145,14 +145,14 @@
 
 [[package]]
 name = "clap"
-version = "4.0.26"
+version = "4.0.32"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
+checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
 dependencies = [
- "atty",
  "bitflags",
  "clap_derive",
  "clap_lex",
+ "is-terminal",
  "once_cell",
  "strsim",
  "termcolor",
@@ -160,9 +160,9 @@
 
 [[package]]
 name = "clap_complete"
-version = "4.0.5"
+version = "4.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "96b0fba905b035a30d25c1b585bf1171690712fbb0ad3ac47214963aa4acc36c"
+checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
 dependencies = [
  "clap",
 ]
@@ -191,9 +191,9 @@
 
 [[package]]
 name = "clap_mangen"
-version = "0.2.4"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "aa149477df7854a1497db0def32b8a65bf98f72a14d04ac75b01938285d83420"
+checksum = "904eb24d05ad587557e0f484ddce5c737c30cf81372badb16d13e41c4b8340b1"
 dependencies = [
  "clap",
  "roff",
@@ -236,6 +236,27 @@
 checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
 
 [[package]]
+name = "errno"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
 name = "fastrand"
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -246,9 +267,9 @@
 
 [[package]]
 name = "filetime"
-version = "0.2.18"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
+checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
 dependencies = [
  "cfg-if",
  "libc",
@@ -258,9 +279,9 @@
 
 [[package]]
 name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
 dependencies = [
  "crc32fast",
  "libz-sys",
@@ -319,12 +340,12 @@
 ]
 
 [[package]]
-name = "humansize"
-version = "2.1.2"
+name = "hermit-abi"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "4e682e2bd70ecbcce5209f11a992a4ba001fea8e60acf7860ce007629e6d2756"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
 dependencies = [
- "libm",
+ "libc",
 ]
 
 [[package]]
@@ -347,9 +368,9 @@
 
 [[package]]
 name = "infer"
-version = "0.11.0"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "0a6c16b11a665b26aeeb9b1d7f954cdeb034be38dd00adab4f2ae921a8fee804"
+checksum = "a898e4b7951673fce96614ce5751d13c40fc5674bc2d759288e46c3ab62598b3"
 dependencies = [
  "cfb",
 ]
@@ -364,6 +385,28 @@
 ]
 
 [[package]]
+name = "io-lifetimes"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
 name = "is_executable"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -383,9 +426,9 @@
 
 [[package]]
 name = "itoa"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
 
 [[package]]
 name = "jobserver"
@@ -404,15 +447,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.137"
+version = "0.2.139"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
-
-[[package]]
-name = "libm"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
 
 [[package]]
 name = "libz-sys"
@@ -432,6 +469,12 @@
 checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
+name = "linux-raw-sys"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
+
+[[package]]
 name = "log"
 version = "0.4.17"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -468,9 +511,9 @@
 
 [[package]]
 name = "miniz_oxide"
-version = "0.5.4"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
 dependencies = [
  "adler",
 ]
@@ -486,9 +529,9 @@
 
 [[package]]
 name = "once_cell"
-version = "1.16.0"
+version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
 
 [[package]]
 name = "os_str_bytes"
@@ -498,10 +541,11 @@
 
 [[package]]
 name = "ouch"
-version = "0.4.0"
+version = "0.4.1"
 dependencies = [
  "assert_cmd",
  "atty",
+ "bstr 1.1.0",
  "bzip2",
  "clap",
  "clap_complete",
@@ -509,7 +553,6 @@
  "filetime",
  "flate2",
  "fs-err",
- "humansize",
  "ignore",
  "infer",
  "is_executable",
@@ -526,6 +569,7 @@
  "tempfile",
  "test-strategy",
  "time",
+ "ubyte",
  "xz2",
  "zip",
  "zstd",
@@ -534,9 +578,9 @@
 
 [[package]]
 name = "parse-display"
-version = "0.6.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "3b25af4ef94a8528b41fb49a696e361dc6ef975c782417268072d987ac327964"
+checksum = "6f96cc033d72896bb9a2c239a14e1141c3e2eae6d649e7c10ef4e598d66bc86c"
 dependencies = [
  "once_cell",
  "parse-display-derive",
@@ -545,9 +589,9 @@
 
 [[package]]
 name = "parse-display-derive"
-version = "0.6.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "73f106cced1f4b645e3fca6125105cdf7407e35d1af710f290aac530f6b826b9"
+checksum = "e5587062be441f3d868f7c4c9d13c67f286b03aa679d7f8176ef80bf2ee79e5d"
 dependencies = [
  "once_cell",
  "proc-macro2",
@@ -572,9 +616,9 @@
 
 [[package]]
 name = "predicates"
-version = "2.1.3"
+version = "2.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "ed6bd09a7f7e68f3f0bf710fb7ab9c4615a488b58b5f653382a687701e458c92"
+checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd"
 dependencies = [
  "difflib",
  "itertools",
@@ -623,9 +667,9 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.49"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
 dependencies = [
  "unicode-ident",
 ]
@@ -664,9 +708,9 @@
 
 [[package]]
 name = "quote"
-version = "1.0.21"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
 dependencies = [
  "proc-macro2",
 ]
@@ -758,6 +802,20 @@
 checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
 
 [[package]]
+name = "rustix"
+version = "0.36.6"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
 name = "rusty-fork"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -780,9 +838,9 @@
 
 [[package]]
 name = "serde"
-version = "1.0.147"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
 
 [[package]]
 name = "snap"
@@ -821,9 +879,9 @@
 
 [[package]]
 name = "syn"
-version = "1.0.103"
+version = "1.0.107"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -919,10 +977,16 @@
 ]
 
 [[package]]
+name = "ubyte"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "c81f0dae7d286ad0d9366d7679a77934cfc3cf3a8d67e82669794412b2368fe6"
+
+[[package]]
 name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
 
 [[package]]
 name = "uuid"
@@ -1089,9 +1153,9 @@
 
 [[package]]
 name = "zstd"
-version = "0.12.0+zstd.1.5.2"
+version = "0.12.1+zstd.1.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "b8148aa921e9d53217ab9322f8553bd130f7ae33489db68b381d76137d2e6374"
+checksum = "5c947d2adc84ff9a59f2e3c03b81aa4128acf28d6ad7d56273f7e8af14e47bea"
 dependencies = [
  "zstd-safe",
 ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/Cargo.toml new/ouch-0.4.1~0/Cargo.toml
--- old/ouch-0.4.0~0/Cargo.toml 2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/Cargo.toml 2023-01-05 23:15:43.000000000 +0100
@@ -1,35 +1,36 @@
 [package]
 name = "ouch"
-version = "0.4.0"
+version = "0.4.1"
 authors = ["Vinícius Rodrigues Miguel <vrmigue...@gmail.com>", "João M. 
Bezerra <marcosp...@hotmail.com>"]
 edition = "2021"
 readme = "README.md"
 repository = "https://github.com/ouch-org/ouch";
 license = "MIT"
-keywords = ["decompression", "compression", "zip", "tar", "gzip", 
"accessibility", "a11y"]
+keywords = ["decompression", "compression", "cli"]
 categories = ["command-line-utilities", "compression", "encoding"]
 description = "A command-line utility for easily compressing and decompressing 
files and directories."
 
 [dependencies]
 atty = "0.2.14"
+bstr = { version = "1.1.0", default-features = false, features = ["std"] }
 bzip2 = "0.4.3"
-clap = { version = "4.0.26", features = ["derive", "env"] }
-filetime = "0.2.18"
-flate2 = { version = "1.0.24", default-features = false }
+clap = { version = "4.0.32", features = ["derive", "env"] }
+filetime = "0.2.19"
+flate2 = { version = "1.0.25", default-features = false }
 fs-err = "2.9.0"
-humansize = "2.1.2"
 ignore = "0.4.18"
-libc = "0.2.137"
+libc = "0.2.139"
 linked-hash-map = "0.5.6"
 lzzzz = "1.0.4"
-once_cell = "1.16.0"
+once_cell = "1.17.0"
 same-file = "1.0.6"
 snap = "1.1.0"
 tar = "0.4.38"
 tempfile = "3.3.0"
+ubyte = { version = "0.10.3", default-features = false }
 xz2 = "0.1.7"
 zip = { version = "0.6.3", default-features = false, features = ["time"] }
-zstd = { version = "0.12.0", default-features = false }
+zstd = { version = "0.12.1", default-features = false }
 # zstd-sys > 2.0.1 unconditionally enables thin LTO and causes CI to fail
 # https://github.com/gyscos/zstd-rs/pull/155
 zstd-sys = "=2.0.1"
@@ -41,14 +42,14 @@
 is_executable = "1.0.1"
 
 [build-dependencies]
-clap = { version = "4.0.26", features = ["derive", "env", "string"] }
-clap_complete = "4.0.5"
-clap_mangen = "0.2.4"
+clap = { version = "4.0.32", features = ["derive", "env", "string"] }
+clap_complete = "4.0.7"
+clap_mangen = "0.2.6"
 
 [dev-dependencies]
-assert_cmd = "2.0.6"
-infer = "0.11.0"
-parse-display = "0.6.0"
+assert_cmd = "2.0.7"
+infer = "0.12.0"
+parse-display = "0.8.0"
 proptest = "1.0.0"
 rand = { version = "0.8.5", default-features = false, features = ["small_rng", 
"std"] }
 test-strategy = "0.2.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/LICENSE new/ouch-0.4.1~0/LICENSE
--- old/ouch-0.4.0~0/LICENSE    2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/LICENSE    2023-01-05 23:15:43.000000000 +0100
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2021-2022 Vinícius R. Miguel, João Marcos P. Bezerra and 
contributors
+Copyright (c) 2021-2023 Vinícius R. Miguel, João Marcos P. Bezerra and 
contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/README.md new/ouch-0.4.1~0/README.md
--- old/ouch-0.4.0~0/README.md  2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/README.md  2023-01-05 23:15:43.000000000 +0100
@@ -126,6 +126,12 @@
 yay -S ouch
 ```
 
+## On Windows via Scoop
+
+```cmd
+scoop install ouch
+```
+
 ## From crates.io
 
 ```bash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/rust-toolchain 
new/ouch-0.4.1~0/rust-toolchain
--- old/ouch-0.4.0~0/rust-toolchain     2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/rust-toolchain     1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-nightly
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/archive/tar.rs 
new/ouch-0.4.1~0/src/archive/tar.rs
--- old/ouch-0.4.0~0/src/archive/tar.rs 2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/archive/tar.rs 2023-01-05 23:15:43.000000000 +0100
@@ -9,43 +9,43 @@
 };
 
 use fs_err as fs;
-use humansize::{format_size, DECIMAL};
 use same_file::Handle;
+use ubyte::ToByteUnit;
 
 use crate::{
     error::FinalError,
     info,
     list::FileInArchive,
-    utils::{self, FileVisibilityPolicy},
+    utils::{self, EscapedPathDisplay, FileVisibilityPolicy},
     warning,
 };
 
 /// Unpacks the archive given by `archive` into the folder given by `into`.
 /// Assumes that output_folder is empty
-pub fn unpack_archive(reader: Box<dyn Read>, output_folder: &Path) -> 
crate::Result<Vec<PathBuf>> {
+pub fn unpack_archive(reader: Box<dyn Read>, output_folder: &Path, quiet: 
bool) -> crate::Result<usize> {
     assert!(output_folder.read_dir().expect("dir exists").count() == 0);
     let mut archive = tar::Archive::new(reader);
 
-    let mut files_unpacked = vec![];
+    let mut files_unpacked = 0;
     for file in archive.entries()? {
         let mut file = file?;
 
-        let file_path = output_folder.join(file.path()?);
         file.unpack_in(output_folder)?;
 
         // This is printed for every file in the archive and has little
         // importance for most users, but would generate lots of
         // spoken text for users using screen readers, braille displays
         // and so on
+        if !quiet {
+            info!(
+                inaccessible,
+                "{:?} extracted. ({})",
+                utils::strip_cur_dir(&output_folder.join(file.path()?)),
+                file.size().bytes(),
+            );
 
-        info!(
-            inaccessible,
-            "{:?} extracted. ({})",
-            utils::strip_cur_dir(&output_folder.join(file.path()?)),
-            format_size(file.size(), DECIMAL),
-        );
-
-        files_unpacked.push(file_path);
+            files_unpacked += 1;
+        }
     }
 
     Ok(files_unpacked)
@@ -86,6 +86,7 @@
     output_path: &Path,
     writer: W,
     file_visibility_policy: FileVisibilityPolicy,
+    quiet: bool,
 ) -> crate::Result<W>
 where
     W: Write,
@@ -118,7 +119,9 @@
             // little importance for most users, but would generate lots of
             // spoken text for users using screen readers, braille displays
             // and so on
-            info!(inaccessible, "Compressing '{}'.", utils::to_utf(path));
+            if !quiet {
+                info!(inaccessible, "Compressing '{}'.", 
EscapedPathDisplay::new(path));
+            }
 
             if path.is_dir() {
                 builder.append_dir(path, path)?;
@@ -137,7 +140,7 @@
                 builder.append_file(path, file.file_mut()).map_err(|err| {
                     FinalError::with_title("Could not create archive")
                         .detail("Unexpected error while trying to read file")
-                        .detail(format!("Error: {}.", err))
+                        .detail(format!("Error: {err}."))
                 })?;
             }
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/archive/zip.rs 
new/ouch-0.4.1~0/src/archive/zip.rs
--- old/ouch-0.4.0~0/src/archive/zip.rs 2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/archive/zip.rs 2023-01-05 23:15:43.000000000 +0100
@@ -12,8 +12,8 @@
 
 use filetime::{set_file_mtime, FileTime};
 use fs_err as fs;
-use humansize::{format_size, DECIMAL};
 use same_file::Handle;
+use ubyte::ToByteUnit;
 use zip::{self, read::ZipFile, DateTime, ZipArchive};
 
 use crate::{
@@ -21,21 +21,21 @@
     info,
     list::FileInArchive,
     utils::{
-        self, cd_into_same_dir_as, get_invalid_utf8_paths, 
pretty_format_list_of_paths, strip_cur_dir, to_utf,
-        FileVisibilityPolicy,
+        self, cd_into_same_dir_as, get_invalid_utf8_paths, 
pretty_format_list_of_paths, strip_cur_dir,
+        EscapedPathDisplay, FileVisibilityPolicy,
     },
     warning,
 };
 
 /// Unpacks the archive given by `archive` into the folder given by 
`output_folder`.
 /// Assumes that output_folder is empty
-pub fn unpack_archive<R>(mut archive: ZipArchive<R>, output_folder: &Path) -> 
crate::Result<Vec<PathBuf>>
+pub fn unpack_archive<R>(mut archive: ZipArchive<R>, output_folder: &Path, 
quiet: bool) -> crate::Result<usize>
 where
     R: Read + Seek,
 {
     assert!(output_folder.read_dir().expect("dir exists").count() == 0);
 
-    let mut unpacked_files = Vec::with_capacity(archive.len());
+    let mut unpacked_files = 0;
 
     for idx in 0..archive.len() {
         let mut file = archive.by_index(idx)?;
@@ -54,7 +54,9 @@
                 // importance for most users, but would generate lots of
                 // spoken text for users using screen readers, braille displays
                 // and so on
-                info!(inaccessible, "File {} extracted to \"{}\"", idx, 
file_path.display());
+                if !quiet {
+                    info!(inaccessible, "File {} extracted to \"{}\"", idx, 
file_path.display());
+                }
                 fs::create_dir_all(&file_path)?;
             }
             _is_file @ false => {
@@ -66,12 +68,14 @@
                 let file_path = strip_cur_dir(file_path.as_path());
 
                 // same reason is in _is_dir: long, often not needed text
-                info!(
-                    inaccessible,
-                    "{:?} extracted. ({})",
-                    file_path.display(),
-                    format_size(file.size(), DECIMAL),
-                );
+                if !quiet {
+                    info!(
+                        inaccessible,
+                        "{:?} extracted. ({})",
+                        file_path.display(),
+                        file.size().bytes()
+                    );
+                }
 
                 let mut output_file = fs::File::create(file_path)?;
                 io::copy(&mut file, &mut output_file)?;
@@ -83,7 +87,7 @@
         #[cfg(unix)]
         unix_set_permissions(&file_path, &file)?;
 
-        unpacked_files.push(file_path);
+        unpacked_files += 1;
     }
 
     Ok(unpacked_files)
@@ -135,6 +139,7 @@
     output_path: &Path,
     writer: W,
     file_visibility_policy: FileVisibilityPolicy,
+    quiet: bool,
 ) -> crate::Result<W>
 where
     W: Write + Seek,
@@ -185,7 +190,9 @@
             // little importance for most users, but would generate lots of
             // spoken text for users using screen readers, braille displays
             // and so on
-            info!(inaccessible, "Compressing '{}'.", to_utf(path));
+            if !quiet {
+                info!(inaccessible, "Compressing '{}'.", 
EscapedPathDisplay::new(path));
+            }
 
             let metadata = match path.metadata() {
                 Ok(metadata) => metadata,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/commands/compress.rs 
new/ouch-0.4.1~0/src/commands/compress.rs
--- old/ouch-0.4.0~0/src/commands/compress.rs   2022-11-23 23:04:30.000000000 
+0100
+++ new/ouch-0.4.1~0/src/commands/compress.rs   2023-01-05 23:15:43.000000000 
+0100
@@ -32,6 +32,7 @@
     extensions: Vec<Extension>,
     output_file: fs::File,
     output_path: &Path,
+    quiet: bool,
     question_policy: QuestionPolicy,
     file_visibility_policy: FileVisibilityPolicy,
 ) -> crate::Result<bool> {
@@ -74,7 +75,7 @@
             io::copy(&mut reader, &mut writer)?;
         }
         Tar => {
-            archive::tar::build_archive_from_paths(&files, output_path, &mut 
writer, file_visibility_policy)?;
+            archive::tar::build_archive_from_paths(&files, output_path, &mut 
writer, file_visibility_policy, quiet)?;
             writer.flush()?;
         }
         Zip => {
@@ -88,7 +89,13 @@
 
             let mut vec_buffer = Cursor::new(vec![]);
 
-            archive::zip::build_archive_from_paths(&files, output_path, &mut 
vec_buffer, file_visibility_policy)?;
+            archive::zip::build_archive_from_paths(
+                &files,
+                output_path,
+                &mut vec_buffer,
+                file_visibility_policy,
+                quiet,
+            )?;
             vec_buffer.rewind()?;
             io::copy(&mut vec_buffer, &mut writer)?;
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/commands/decompress.rs 
new/ouch-0.4.1~0/src/commands/decompress.rs
--- old/ouch-0.4.0~0/src/commands/decompress.rs 2022-11-23 23:04:30.000000000 
+0100
+++ new/ouch-0.4.1~0/src/commands/decompress.rs 2023-01-05 23:15:43.000000000 
+0100
@@ -30,6 +30,7 @@
     output_dir: &Path,
     output_file_path: PathBuf,
     question_policy: QuestionPolicy,
+    quiet: bool,
 ) -> crate::Result<()> {
     assert!(output_dir.exists());
     let reader = fs::File::open(input_file_path)?;
@@ -47,8 +48,8 @@
     }] = formats.as_slice()
     {
         let zip_archive = zip::ZipArchive::new(reader)?;
-        let files = if let ControlFlow::Continue(files) = smart_unpack(
-            |output_dir| crate::archive::zip::unpack_archive(zip_archive, 
output_dir),
+        let files_unpacked = if let ControlFlow::Continue(files) = 
smart_unpack(
+            |output_dir| crate::archive::zip::unpack_archive(zip_archive, 
output_dir, quiet),
             output_dir,
             &output_file_path,
             question_policy,
@@ -66,7 +67,7 @@
             accessible,
             "Successfully decompressed archive in {} ({} files).",
             nice_directory_display(output_dir),
-            files.len()
+            files_unpacked
         );
 
         return Ok(());
@@ -107,11 +108,11 @@
 
             io::copy(&mut reader, &mut writer)?;
 
-            vec![output_file_path]
+            1
         }
         Tar => {
             if let ControlFlow::Continue(files) = smart_unpack(
-                |output_dir| crate::archive::tar::unpack_archive(reader, 
output_dir),
+                |output_dir| crate::archive::tar::unpack_archive(reader, 
output_dir, quiet),
                 output_dir,
                 &output_file_path,
                 question_policy,
@@ -135,7 +136,7 @@
             let zip_archive = zip::ZipArchive::new(io::Cursor::new(vec))?;
 
             if let ControlFlow::Continue(files) = smart_unpack(
-                |output_dir| crate::archive::zip::unpack_archive(zip_archive, 
output_dir),
+                |output_dir| crate::archive::zip::unpack_archive(zip_archive, 
output_dir, quiet),
                 output_dir,
                 &output_file_path,
                 question_policy,
@@ -156,7 +157,7 @@
         "Successfully decompressed archive in {}.",
         nice_directory_display(output_dir)
     );
-    info!(accessible, "Files unpacked: {}", files_unpacked.len());
+    info!(accessible, "Files unpacked: {}", files_unpacked);
 
     Ok(())
 }
@@ -167,11 +168,11 @@
 ///   output_dir named after the archive (given by `output_file_path`)
 /// Note: This functions assumes that `output_dir` exists
 fn smart_unpack(
-    unpack_fn: impl FnOnce(&Path) -> crate::Result<Vec<PathBuf>>,
+    unpack_fn: impl FnOnce(&Path) -> crate::Result<usize>,
     output_dir: &Path,
     output_file_path: &Path,
     question_policy: QuestionPolicy,
-) -> crate::Result<ControlFlow<(), Vec<PathBuf>>> {
+) -> crate::Result<ControlFlow<(), usize>> {
     assert!(output_dir.exists());
     let temp_dir = tempfile::tempdir_in(output_dir)?;
     let temp_dir_path = temp_dir.path();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/commands/mod.rs 
new/ouch-0.4.1~0/src/commands/mod.rs
--- old/ouch-0.4.0~0/src/commands/mod.rs        2022-11-23 23:04:30.000000000 
+0100
+++ new/ouch-0.4.1~0/src/commands/mod.rs        2023-01-05 23:15:43.000000000 
+0100
@@ -18,7 +18,8 @@
     info,
     list::ListOptions,
     utils::{
-        self, pretty_format_list_of_paths, to_utf, try_infer_extension, 
user_wants_to_continue, FileVisibilityPolicy,
+        self, pretty_format_list_of_paths, to_utf, try_infer_extension, 
user_wants_to_continue, EscapedPathDisplay,
+        FileVisibilityPolicy,
     },
     warning, Opts, QuestionAction, QuestionPolicy, Subcommand,
 };
@@ -67,6 +68,31 @@
     None
 }
 
+/// In the context of listing archives, this function checks if `ouch` was 
told to list
+/// the contents of a compressed file that is not an archive
+fn check_for_non_archive_formats(files: &[PathBuf], formats: 
&[Vec<Extension>]) -> crate::Result<()> {
+    let mut not_archives = files
+        .iter()
+        .zip(formats)
+        .filter(|(_, formats)| 
!formats.first().map(Extension::is_archive).unwrap_or(false))
+        .map(|(path, _)| path)
+        .peekable();
+
+    if not_archives.peek().is_some() {
+        let not_archives: Vec<_> = not_archives.collect();
+        let error = FinalError::with_title("Cannot list archive contents")
+            .detail("Only archives can have their contents listed")
+            .detail(format!(
+                "Files are not archives: {}",
+                pretty_format_list_of_paths(&not_archives)
+            ));
+
+        return Err(error.into());
+    }
+
+    Ok(())
+}
+
 /// This function checks what command needs to be run and performs A LOT of 
ahead-of-time checks
 /// to assume everything is OK.
 ///
@@ -90,7 +116,7 @@
             let formats = extension::extensions_from_path(&output_path);
 
             let first_format = formats.first().ok_or_else(|| {
-                let output_path = to_utf(&output_path);
+                let output_path = EscapedPathDisplay::new(&output_path);
                 FinalError::with_title(format!("Cannot compress to 
'{output_path}'."))
                     .detail("You shall supply the compression format")
                     .hint("Try adding supported extensions (see --help):")
@@ -113,43 +139,43 @@
                 // To          file.tar.bz.xz
                 let suggested_output_path = 
build_archive_file_suggestion(&output_path, ".tar")
                     .expect("output path should contain a compression format");
-                let output_path = to_utf(&output_path);
+                let output_path = EscapedPathDisplay::new(&output_path);
                 let first_detail_message = if is_multiple_inputs {
                     "You are trying to compress multiple files."
                 } else {
                     "You are trying to compress a folder."
                 };
 
-                let error = FinalError::with_title(format!("Cannot compress to 
'{}'.", output_path))
+                let error = FinalError::with_title(format!("Cannot compress to 
'{output_path}'."))
                     .detail(first_detail_message)
                     .detail(format!(
-                        "The compression format '{}' does not accept multiple 
files.",
-                        &formats[0]
+                        "The compression format '{first_format}' does not 
accept multiple files.",
                     ))
                     .detail("Formats that bundle files into an archive are 
.tar and .zip.")
-                    .hint(format!("Try inserting '.tar' or '.zip' before 
'{}'.", &formats[0]))
-                    .hint(format!("From: {}", output_path))
-                    .hint(format!("To:   {}", suggested_output_path));
+                    .hint(format!("Try inserting '.tar' or '.zip' before 
'{first_format}'."))
+                    .hint(format!("From: {output_path}"))
+                    .hint(format!("To:   {suggested_output_path}"));
 
                 return Err(error.into());
             }
 
             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)
-                    ));
+                let error = FinalError::with_title(format!(
+                    "Cannot compress to '{}'.",
+                    EscapedPathDisplay::new(&output_path)
+                ))
+                .detail(format!("Found the format '{format}' in an incorrect 
position."))
+                .detail(format!(
+                    "'{format}' can only be used at the start of the file 
extension."
+                ))
+                .hint(format!(
+                    "If you wish to compress multiple files, start the 
extension with '{format}'."
+                ))
+                .hint(format!(
+                    "Otherwise, remove the last '{}' from '{}'.",
+                    format,
+                    EscapedPathDisplay::new(&output_path)
+                ));
 
                 return Err(error.into());
             }
@@ -164,6 +190,7 @@
                 formats,
                 output_file,
                 &output_path,
+                args.quiet,
                 question_policy,
                 file_visibility_policy,
             );
@@ -181,7 +208,10 @@
                 // out that we left a possibly CORRUPTED file at `output_path`
                 if utils::remove_file_or_dir(&output_path).is_err() {
                     eprintln!("{red}FATAL ERROR:\n", red = *colors::RED);
-                    eprintln!("  Ouch failed to delete the file '{}'.", 
to_utf(&output_path));
+                    eprintln!(
+                        "  Ouch failed to delete the file '{}'.",
+                        EscapedPathDisplay::new(&output_path)
+                    );
                     eprintln!("  Please delete it manually.");
                     eprintln!("  This file is corrupted if compression didn't 
finished.");
 
@@ -214,7 +244,7 @@
                 .map(|(input_path, _)| PathBuf::from(input_path))
                 .collect();
 
-            if !files_missing_format.is_empty() {
+            if let Some(path) = files_missing_format.first() {
                 let error = FinalError::with_title("Cannot decompress files 
without extensions")
                     .detail(format!(
                         "Files without supported extensions: {}",
@@ -227,7 +257,7 @@
                     .hint("Or overwrite this option with the '--format' flag:")
                     .hint(format!(
                         "  ouch decompress {} --format tar.gz",
-                        to_utf(&files_missing_format[0])
+                        EscapedPathDisplay::new(path),
                     ));
 
                 return Err(error.into());
@@ -236,10 +266,6 @@
             // The directory that will contain the output files
             // We default to the current directory if the user didn't specify 
an output directory with --dir
             let output_dir = if let Some(dir) = output_dir {
-                if !utils::clear_path(&dir, question_policy)? {
-                    // User doesn't want to overwrite
-                    return Ok(());
-                }
                 utils::create_dir_if_non_existent(&dir)?;
                 dir
             } else {
@@ -248,14 +274,21 @@
 
             for ((input_path, formats), file_name) in 
files.iter().zip(formats).zip(output_paths) {
                 let output_file_path = output_dir.join(file_name); // Path 
used by single file format archives
-                decompress_file(input_path, formats, &output_dir, 
output_file_path, question_policy)?;
+                decompress_file(
+                    input_path,
+                    formats,
+                    &output_dir,
+                    output_file_path,
+                    question_policy,
+                    args.quiet,
+                )?;
             }
         }
         Subcommand::List { archives: files, tree } => {
             let mut formats = vec![];
 
             for path in files.iter() {
-                let (_, file_formats) = 
extension::separate_known_extensions_from_name(path);
+                let file_formats = extension::extensions_from_path(path);
                 formats.push(file_formats);
             }
 
@@ -263,23 +296,8 @@
                 return Ok(());
             }
 
-            let not_archives: Vec<PathBuf> = files
-                .iter()
-                .zip(&formats)
-                .filter(|(_, formats)| 
!formats.first().map(Extension::is_archive).unwrap_or(false))
-                .map(|(path, _)| path.clone())
-                .collect();
-
-            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: {}",
-                        pretty_format_list_of_paths(&not_archives)
-                    ));
-
-                return Err(error.into());
-            }
+            // Ensure we were not told to list the content of a non-archive 
compressed file
+            check_for_non_archive_formats(&files, &formats)?;
 
             let list_options = ListOptions { tree };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/error.rs 
new/ouch-0.4.1~0/src/error.rs
--- old/ouch-0.4.0~0/src/error.rs       2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/error.rs       2023-01-05 23:15:43.000000000 +0100
@@ -76,7 +76,7 @@
             if is_running_in_accessible_mode() {
                 write!(f, "\n{}hints:{}", *GREEN, *RESET)?;
                 for hint in &self.hints {
-                    write!(f, "\n{}", hint)?;
+                    write!(f, "\n{hint}")?;
                 }
             } else {
                 for hint in &self.hints {
@@ -138,7 +138,7 @@
             Error::Custom { reason } => reason.clone(),
         };
 
-        write!(f, "{}", err)
+        write!(f, "{err}")
     }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/extension.rs 
new/ouch-0.4.1~0/src/extension.rs
--- old/ouch-0.4.0~0/src/extension.rs   2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/extension.rs   2023-01-05 23:15:43.000000000 +0100
@@ -1,6 +1,8 @@
 //! Our representation of all the supported compression formats.
 
-use std::{ffi::OsStr, fmt, path::Path};
+use std::{fmt, path::Path};
+
+use bstr::ByteSlice;
 
 use self::CompressionFormat::*;
 use crate::warning;
@@ -104,54 +106,61 @@
     "zst",
 ];
 
+pub fn to_extension(ext: &[u8]) -> Option<Extension> {
+    Some(Extension::new(
+        match ext {
+            b"tar" => &[Tar],
+            b"tgz" => &[Tar, Gzip],
+            b"tbz" | b"tbz2" => &[Tar, Bzip],
+            b"tlz4" => &[Tar, Lz4],
+            b"txz" | b"tlzma" => &[Tar, Lzma],
+            b"tsz" => &[Tar, Snappy],
+            b"tzst" => &[Tar, Zstd],
+            b"zip" => &[Zip],
+            b"bz" | b"bz2" => &[Bzip],
+            b"gz" => &[Gzip],
+            b"lz4" => &[Lz4],
+            b"xz" | b"lzma" => &[Lzma],
+            b"sz" => &[Snappy],
+            b"zst" => &[Zstd],
+            _ => return None,
+        },
+        ext.to_str_lossy(),
+    ))
+}
+
+pub fn split_extension<'a>(name: &mut &'a [u8]) -> Option<&'a [u8]> {
+    let (new_name, ext) = name.rsplit_once_str(b".")?;
+    if matches!(new_name, b"" | b"." | b"..") {
+        return None;
+    }
+    *name = new_name;
+    Some(ext)
+}
+
 /// Extracts extensions from a path.
 ///
 /// Returns both the remaining path and the list of extension objects
-pub fn separate_known_extensions_from_name(mut path: &Path) -> (&Path, 
Vec<Extension>) {
+pub fn separate_known_extensions_from_name(path: &Path) -> (&Path, 
Vec<Extension>) {
     let mut extensions = vec![];
 
-    if let Some(file_stem) = path.file_stem().and_then(OsStr::to_str) {
-        let file_stem = file_stem.trim_matches('.');
+    let Some(mut name) = path.file_name().and_then(<[u8] as 
ByteSlice>::from_os_str) else {
+        return (path, extensions);
+    };
+
+    // While there is known extensions at the tail, grab them
+    while let Some(extension) = split_extension(&mut 
name).and_then(to_extension) {
+        extensions.insert(0, extension);
+    }
 
+    if let Ok(name) = name.to_str() {
+        let file_stem = name.trim_matches('.');
         if SUPPORTED_EXTENSIONS.contains(&file_stem) {
             warning!("Received a file with name '{file_stem}', but {file_stem} 
was expected as the extension.");
         }
     }
 
-    // While there is known extensions at the tail, grab them
-    while let Some(extension) = path.extension().and_then(OsStr::to_str) {
-        let formats: &[CompressionFormat] = match extension {
-            "tar" => &[Tar],
-            "tgz" => &[Tar, Gzip],
-            "tbz" | "tbz2" => &[Tar, Bzip],
-            "tlz4" => &[Tar, Lz4],
-            "txz" | "tlzma" => &[Tar, Lzma],
-            "tsz" => &[Tar, Snappy],
-            "tzst" => &[Tar, Zstd],
-            "zip" => &[Zip],
-            "bz" | "bz2" => &[Bzip],
-            "gz" => &[Gzip],
-            "lz4" => &[Lz4],
-            "xz" | "lzma" => &[Lzma],
-            "sz" => &[Snappy],
-            "zst" => &[Zstd],
-            _ => break,
-        };
-
-        let extension = Extension::new(formats, extension);
-        extensions.push(extension);
-
-        // Update for the next iteration
-        path = if let Some(stem) = path.file_stem() {
-            Path::new(stem)
-        } else {
-            Path::new("")
-        };
-    }
-    // Put the extensions in the correct order: left to right
-    extensions.reverse();
-
-    (path, extensions)
+    (name.to_path().unwrap(), extensions)
 }
 
 /// Extracts extensions from a path, return only the list of extension objects
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/list.rs new/ouch-0.4.1~0/src/list.rs
--- old/ouch-0.4.0~0/src/list.rs        2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/list.rs        2023-01-05 23:15:43.000000000 +0100
@@ -57,7 +57,7 @@
     if is_dir {
         // if colors are deactivated, print final / to mark directories
         if BLUE.is_empty() {
-            println!("{}/", name);
+            println!("{name}/");
         // if in ACCESSIBLE mode, use colors but print final / in case colors
         // aren't read out aloud with a screen reader or aren't printed on a
         // braille reader
@@ -68,7 +68,7 @@
         }
     } else {
         // not a dir -> just print the file name
-        println!("{}", name);
+        println!("{name}");
     }
 }
 
@@ -142,7 +142,7 @@
                 false => draw::FINAL_BRANCH,
             };
 
-            print!("{}{}", prefix, final_part);
+            print!("{prefix}{final_part}");
             let is_dir = match self.file {
                 Some(FileInArchive { is_dir, .. }) => is_dir,
                 None => true,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/main.rs new/ouch-0.4.1~0/src/main.rs
--- old/ouch-0.4.0~0/src/main.rs        2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/main.rs        2023-01-05 23:15:43.000000000 +0100
@@ -31,7 +31,7 @@
 
 fn main() {
     if let Err(err) = run() {
-        eprintln!("{}", err);
+        eprintln!("{err}");
         std::process::exit(EXIT_FAILURE);
     }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/opts.rs new/ouch-0.4.1~0/src/opts.rs
--- old/ouch-0.4.0~0/src/opts.rs        2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/opts.rs        2023-01-05 23:15:43.000000000 +0100
@@ -26,11 +26,15 @@
     pub accessible: bool,
 
     /// Ignores hidden files
-    #[arg(short = 'H', long)]
+    #[arg(short = 'H', long, global = true)]
     pub hidden: bool,
 
+    /// Silences output
+    #[arg(short = 'q', long, global = true)]
+    pub quiet: bool,
+
     /// Ignores files matched by git's ignore files
-    #[arg(short = 'g', long)]
+    #[arg(short = 'g', long, global = true)]
     pub gitignore: bool,
 
     /// Ouch and claps subcommands
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/utils/formatting.rs 
new/ouch-0.4.1~0/src/utils/formatting.rs
--- old/ouch-0.4.0~0/src/utils/formatting.rs    2022-11-23 23:04:30.000000000 
+0100
+++ new/ouch-0.4.1~0/src/utils/formatting.rs    2023-01-05 23:15:43.000000000 
+0100
@@ -1,7 +1,45 @@
-use std::{borrow::Cow, path::Path};
+use std::{borrow::Cow, fmt::Display, path::Path};
 
 use crate::CURRENT_DIRECTORY;
 
+/// Converts invalid UTF-8 bytes to the Unicode replacement codepoint (�) in 
its Display implementation.
+pub struct EscapedPathDisplay<'a> {
+    path: &'a Path,
+}
+
+impl<'a> EscapedPathDisplay<'a> {
+    pub fn new(path: &'a Path) -> Self {
+        Self { path }
+    }
+}
+
+#[cfg(unix)]
+impl Display for EscapedPathDisplay<'_> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        use std::os::unix::prelude::OsStrExt;
+
+        let bstr = bstr::BStr::new(self.path.as_os_str().as_bytes());
+
+        write!(f, "{bstr}")
+    }
+}
+
+#[cfg(windows)]
+impl Display for EscapedPathDisplay<'_> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        use std::{char, fmt::Write, os::windows::prelude::OsStrExt};
+
+        let utf16 = self.path.as_os_str().encode_wide();
+        let chars = char::decode_utf16(utf16).map(|decoded| 
decoded.unwrap_or(char::REPLACEMENT_CHARACTER));
+
+        for char in chars {
+            f.write_char(char)?;
+        }
+
+        Ok(())
+    }
+}
+
 /// Converts an OsStr to utf8 with custom formatting.
 ///
 /// This is different from [`Path::display`].
@@ -9,7 +47,7 @@
 /// See <https://gist.github.com/marcospb19/ebce5572be26397cf08bbd0fd3b65ac1> 
for a comparison.
 pub fn to_utf(os_str: &Path) -> Cow<str> {
     let format = || {
-        let text = format!("{:?}", os_str);
+        let text = format!("{os_str:?}");
         Cow::Owned(text.trim_matches('"').to_string())
     };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/utils/fs.rs 
new/ouch-0.4.1~0/src/utils/fs.rs
--- old/ouch-0.4.0~0/src/utils/fs.rs    2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/utils/fs.rs    2023-01-05 23:15:43.000000000 +0100
@@ -8,8 +8,8 @@
 
 use fs_err as fs;
 
-use super::{to_utf, user_wants_to_overwrite};
-use crate::{extension::Extension, info, QuestionPolicy};
+use super::user_wants_to_overwrite;
+use crate::{extension::Extension, info, utils::EscapedPathDisplay, 
QuestionPolicy};
 
 /// Remove `path` asking the user to overwrite if necessary.
 ///
@@ -41,7 +41,7 @@
         fs::create_dir_all(path)?;
         // creating a directory is an important change to the file system we
         // should always inform the user about
-        info!(accessible, "directory {} created.", to_utf(path));
+        info!(accessible, "directory {} created.", 
EscapedPathDisplay::new(path));
     }
     Ok(())
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/utils/mod.rs 
new/ouch-0.4.1~0/src/utils/mod.rs
--- old/ouch-0.4.0~0/src/utils/mod.rs   2022-11-23 23:04:30.000000000 +0100
+++ new/ouch-0.4.1~0/src/utils/mod.rs   2023-01-05 23:15:43.000000000 +0100
@@ -10,7 +10,7 @@
 mod question;
 
 pub use file_visibility::FileVisibilityPolicy;
-pub use formatting::{nice_directory_display, pretty_format_list_of_paths, 
strip_cur_dir, to_utf};
+pub use formatting::{nice_directory_display, pretty_format_list_of_paths, 
strip_cur_dir, to_utf, EscapedPathDisplay};
 pub use fs::{
     cd_into_same_dir_as, clear_path, create_dir_if_non_existent, is_symlink, 
remove_file_or_dir, try_infer_extension,
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ouch-0.4.0~0/src/utils/question.rs 
new/ouch-0.4.1~0/src/utils/question.rs
--- old/ouch-0.4.0~0/src/utils/question.rs      2022-11-23 23:04:30.000000000 
+0100
+++ new/ouch-0.4.1~0/src/utils/question.rs      2023-01-05 23:15:43.000000000 
+0100
@@ -86,7 +86,7 @@
             let path = to_utf(strip_cur_dir(path));
             let path = Some(&*path);
             let placeholder = Some("FILE");
-            Confirmation::new(&format!("Do you want to {} 'FILE'?", action), 
placeholder).ask(path)
+            Confirmation::new(&format!("Do you want to {action} 'FILE'?"), 
placeholder).ask(path)
         }
     }
 }

++++++ vendor.tar.xz ++++++
/work/SRC/openSUSE:Factory/ouch/vendor.tar.xz 
/work/SRC/openSUSE:Factory/.ouch.new.1563/vendor.tar.xz differ: char 27, line 1

Reply via email to