Update to clap from structopt (#759)

pull/760/head
Rafał Mikrut 2 years ago committed by GitHub
parent 486bec15ad
commit d42e17c15f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

3
.gitignore vendored

@ -8,4 +8,5 @@ TestSuite*
*.snap *.snap
flatpak/ flatpak/
*.zip *.zip
*.zst *.zst
*.profraw

224
Cargo.lock generated

@ -66,15 +66,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.57" version = "1.0.57"
@ -350,17 +341,41 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.34.0" version = "3.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
dependencies = [ dependencies = [
"ansi_term",
"atty", "atty",
"bitflags", "bitflags",
"strsim 0.8.0", "clap_derive",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap", "textwrap",
"unicode-width", ]
"vec_map",
[[package]]
name = "clap_derive"
version = "3.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613"
dependencies = [
"os_str_bytes",
] ]
[[package]] [[package]]
@ -395,9 +410,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.4" version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
@ -416,26 +431,26 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.8" version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
"lazy_static",
"memoffset", "memoffset",
"once_cell",
"scopeguard", "scopeguard",
] ]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.8" version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"lazy_static", "once_cell",
] ]
[[package]] [[package]]
@ -452,9 +467,9 @@ dependencies = [
name = "czkawka_cli" name = "czkawka_cli"
version = "4.1.0" version = "4.1.0"
dependencies = [ dependencies = [
"clap",
"czkawka_core", "czkawka_core",
"image_hasher", "image_hasher",
"structopt",
] ]
[[package]] [[package]]
@ -529,7 +544,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"hashbrown 0.12.1", "hashbrown",
"lock_api", "lock_api",
"parking_lot_core", "parking_lot_core",
] ]
@ -769,9 +784,9 @@ dependencies = [
[[package]] [[package]]
name = "flume" name = "flume"
version = "0.10.12" version = "0.10.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" checksum = "1ceeb589a3157cac0ab8cc585feb749bd2cea5cb55a6ee802ad72d9fd38303da"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@ -962,14 +977,14 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.6" version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys", "js-sys",
"libc", "libc",
"wasi", "wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen", "wasm-bindgen",
] ]
@ -1040,7 +1055,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64" checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"heck 0.4.0", "heck",
"proc-macro-crate", "proc-macro-crate",
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
@ -1199,27 +1214,12 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" checksum = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1"
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.1" version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.0" version = "0.4.0"
@ -1301,7 +1301,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim 0.10.0", "strsim",
"syn", "syn",
"unic-langid", "unic-langid",
] ]
@ -1404,19 +1404,19 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.8.2" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown 0.11.2", "hashbrown",
] ]
[[package]] [[package]]
name = "infer" name = "infer"
version = "0.8.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f98856089d7ef1e861afada561bc23897918cfdfda49fe4f90ae9152ac86c3" checksum = "e035cede526e0b21d5adffc9fa0eb4ef5d6026fe9c5b0bfe8084b9472b587a55"
dependencies = [ dependencies = [
"cfb", "cfb",
] ]
@ -1494,9 +1494,9 @@ dependencies = [
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.57" version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -1821,9 +1821,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "open" name = "open"
version = "2.1.3" version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2423ffbf445b82e58c3b1543655968923dd06f85432f10be2bb4f1b7122f98c" checksum = "360bcc8316bf6363aa3954c3ccc4de8add167b087e0259190a043c9514f910fe"
dependencies = [ dependencies = [
"pathdiff", "pathdiff",
"windows-sys", "windows-sys",
@ -1835,6 +1835,12 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91409674c628d07a6b4b79cc877c6b63ba5ccbfbadddd77ca822f55069ed1bd4" checksum = "91409674c628d07a6b4b79cc877c6b63ba5ccbfbadddd77ca822f55069ed1bd4"
[[package]]
name = "os_str_bytes"
version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
[[package]] [[package]]
name = "pango" name = "pango"
version = "0.15.10" version = "0.15.10"
@ -2280,7 +2286,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [ dependencies = [
"semver 1.0.9", "semver 1.0.10",
] ]
[[package]] [[package]]
@ -2372,9 +2378,9 @@ dependencies = [
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.9" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c"
[[package]] [[package]]
name = "semver-parser" name = "semver-parser"
@ -2521,42 +2527,12 @@ dependencies = [
"unicode-normalization", "unicode-normalization",
] ]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "structopt"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck 0.3.3",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.1" version = "2.4.1"
@ -2753,7 +2729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
dependencies = [ dependencies = [
"cfg-expr", "cfg-expr",
"heck 0.4.0", "heck",
"pkg-config", "pkg-config",
"toml", "toml",
"version-compare", "version-compare",
@ -2774,14 +2750,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "textwrap" name = "termcolor"
version = "0.11.0" version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [ dependencies = [
"unicode-width", "winapi-util",
] ]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.31" version = "1.0.31"
@ -2840,7 +2822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "wasi 0.10.0+wasi-snapshot-preview1",
"winapi", "winapi",
] ]
@ -2981,9 +2963,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@ -2994,18 +2976,6 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]] [[package]]
name = "url" name = "url"
version = "2.2.2" version = "2.2.2"
@ -3020,15 +2990,9 @@ dependencies = [
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.1.1" version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6d5d669b51467dcf7b2f1a796ce0f955f05f01cafda6c19d6e95f730df29238"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
[[package]] [[package]]
name = "version-compare" name = "version-compare"
@ -3076,11 +3040,17 @@ version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.80" version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -3088,9 +3058,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.80" version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
@ -3103,9 +3073,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.80" version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -3113,9 +3083,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.80" version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3126,9 +3096,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.80" version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
[[package]] [[package]]
name = "weezl" name = "weezl"

@ -4,12 +4,17 @@
- Fix removing only one item from list view - [#466](https://github.com/qarmin/czkawka/pull/466) - Fix removing only one item from list view - [#466](https://github.com/qarmin/czkawka/pull/466)
- Fix showing help command in duplicate CLI mode - [#720](https://github.com/qarmin/czkawka/pull/720) - Fix showing help command in duplicate CLI mode - [#720](https://github.com/qarmin/czkawka/pull/720)
- Fix freeze when not choosing any tag in similar music mode - [TODO]() - Fix freeze when not choosing any tag in similar music mode - [TODO]()
- Fix preview of files with non-lowercase extensions - [#694](https://github.com/qarmin/czkawka/pull/694)
- Read more tags from music files - [#705](https://github.com/qarmin/czkawka/pull/705) - Read more tags from music files - [#705](https://github.com/qarmin/czkawka/pull/705)
- Improve checking for invalid extensions - [#705](https://github.com/qarmin/czkawka/pull/705) - Improve checking for invalid extensions - [#705](https://github.com/qarmin/czkawka/pull/705), [#747](https://github.com/qarmin/czkawka/pull/747), [#749](https://github.com/qarmin/czkawka/pull/749)
- Support for finding invalid PDF files - [#705](https://github.com/qarmin/czkawka/pull/705) - Support for finding invalid PDF files - [#705](https://github.com/qarmin/czkawka/pull/705)
- Re-enable checking for broken music files(`libasound.so.2` no longer needed) - [#705](https://github.com/qarmin/czkawka/pull/705) - Re-enable checking for broken music files(`libasound.so.2` no longer needed) - [#705](https://github.com/qarmin/czkawka/pull/705)
- Fix disabled ui when using invalid settings in similar music - [#740](https://github.com/qarmin/czkawka/pull/740) - Fix disabled ui when using invalid settings in similar music - [#740](https://github.com/qarmin/czkawka/pull/740)
- Speedup searching for invalid extensions - [#740](https://github.com/qarmin/czkawka/pull/740) - Speedup searching for invalid extensions - [#740](https://github.com/qarmin/czkawka/pull/740)
- Support for finding the smallest files - [#741](https://github.com/qarmin/czkawka/pull/741)
- Improve Windows CI - [#749](https://github.com/qarmin/czkawka/pull/749)
- Ability to check for broken files by types - [#749](https://github.com/qarmin/czkawka/pull/749)
- Add heif and Webp files support - [#750](https://github.com/qarmin/czkawka/pull/750)
## Version 4.1.0 - 24.04.2022r ## Version 4.1.0 - 24.04.2022r
- New mode - finding files whose content not match with their extension - [#678](https://github.com/qarmin/czkawka/pull/678) - New mode - finding files whose content not match with their extension - [#678](https://github.com/qarmin/czkawka/pull/678)

@ -2,13 +2,6 @@
**Czkawka** (_tch•kav•ka_ (IPA: [ʈ͡ʂkafka]), "hiccup" in Polish) is a simple, fast and free app to remove unnecessary files from your computer. **Czkawka** (_tch•kav•ka_ (IPA: [ʈ͡ʂkafka]), "hiccup" in Polish) is a simple, fast and free app to remove unnecessary files from your computer.
## UNSTABLE WARNING
**Currently, master branch of this repository contains unstable GTK 4 port, so multiple regression, broken features etc. are expected.**
**You can use old stable version built with GTK 3 - [4.1.0](https://github.com/qarmin/czkawka/releases/tag/4.1.0) or compile app from git before GTK 4 PR merge.**
**Due build problems Windows binaries are not available yet, you can help by creating/modifying CI to produce valid windows binaries**
## Features ## Features
- Written in memory-safe Rust - Written in memory-safe Rust
- Amazingly fast - due to using more or less advanced algorithms and multithreading - Amazingly fast - due to using more or less advanced algorithms and multithreading
@ -32,7 +25,6 @@
- Broken Files - Finds files that are invalid or corrupted - Broken Files - Finds files that are invalid or corrupted
- Bad Extensions - Lists files whose content not match with their extension - Bad Extensions - Lists files whose content not match with their extension
<!-- The GIF thingy -->
![Czkawka](https://user-images.githubusercontent.com/41945903/145280350-506f7e94-4db0-4de7-a68d-6e7c26bbd2bf.gif) ![Czkawka](https://user-images.githubusercontent.com/41945903/145280350-506f7e94-4db0-4de7-a68d-6e7c26bbd2bf.gif)
## How do I use it? ## How do I use it?
@ -56,8 +48,8 @@ I prepared a disk and performed a test without any folder exceptions and with di
I set the minimal file size to check to 1KB on all programs. I set the minimal file size to check to 1KB on all programs.
| App | Executing Time | | App | Executing Time |
|:---------------------------:|:--------------:| |:----------------------------|:--------------:|
| FSlint 2.4.7 (First Run) | 86s | | FSlint 2.4.7 (First Run) | 86s |
| FSlint 2.4.7 (Second Run) | 43s | | FSlint 2.4.7 (Second Run) | 43s |
| Czkawka 3.0.0 (First Run) | 8s | | Czkawka 3.0.0 (First Run) | 8s |
@ -67,11 +59,11 @@ I set the minimal file size to check to 1KB on all programs.
I used Mprof for checking memory usage of FSlint and DupeGuru, and Heaptrack for Czkawka. I used Mprof for checking memory usage of FSlint and DupeGuru, and Heaptrack for Czkawka.
| App | Idle Ram | Max Operational Ram Usage | Stabilized after search | | App | Idle Ram | Max Operational Ram Usage | Stabilized after search |
|:--------------:|:--------:|:-------------------------:|:-----------------------:| |:----------------|:--------:|:-------------------------:|:-----------------------:|
| FSlint 2.4.7 | 62 MB | 164 MB | 158 MB | | FSlint 2.4.7 | 62 MB | 164 MB | 158 MB |
| Dupeguru 4.1.1 | 90 MB | 170 MB | 166 MB | | Dupeguru 4.1.1 | 90 MB | 170 MB | 166 MB |
| Czkawka 3.0.0 | 12 MB | 122 MB | 60 MB | | Czkawka 3.0.0 | 12 MB | 122 MB | 60 MB |
In Dupeguru, I enabled checking images with different dimensions to match Czkawka behavior. In Dupeguru, I enabled checking images with different dimensions to match Czkawka behavior.
@ -79,8 +71,8 @@ Both apps use a caching mechanism, so the second scan is really fast.
Similar images which check 10949 files that occupied 6.6 GB Similar images which check 10949 files that occupied 6.6 GB
| App | Scan time | | App | Scan time |
|:---------------------------:|:---------:| |:----------------------------|:---------:|
| Czkawka 3.0.0 (First Run) | 276s | | Czkawka 3.0.0 (First Run) | 276s |
| Czkawka 3.0.0 (Second Run) | 1s | | Czkawka 3.0.0 (Second Run) | 1s |
| DupeGuru 4.1.1 (First Run) | 539s | | DupeGuru 4.1.1 (First Run) | 539s |
@ -88,12 +80,12 @@ Similar images which check 10949 files that occupied 6.6 GB
Similar images which check 349 image files that occupied 1.7 GB Similar images which check 349 image files that occupied 1.7 GB
| App | Scan time | | App | Scan time |
|:---------------------------:|:----------| |:----------------------------|:----------:|
| Czkawka 3.0.0 (First Run) | 54s | | Czkawka 3.0.0 (First Run) | 54s |
| Czkawka 3.0.0 (Second Run) | 1s | | Czkawka 3.0.0 (Second Run) | 1s |
| DupeGuru 4.1.1 (First Run) | 55s | | DupeGuru 4.1.1 (First Run) | 55s |
| DupeGuru 4.1.1 (Second Run) | 1s | | DupeGuru 4.1.1 (Second Run) | 1s |
## Comparison to other tools ## Comparison to other tools
@ -171,9 +163,9 @@ Code is distributed under MIT license.
Icon was created by [jannuary](https://github.com/jannuary) and licensed CC-BY-4.0. Icon was created by [jannuary](https://github.com/jannuary) and licensed CC-BY-4.0.
Windows dark theme is used from [AdMin repo](https://github.com/nrhodes91/AdMin) with MIT license. Windows dark theme is used from project [WhiteSur](https://github.com/slypy/whitesur-gtk4-theme) with MIT license.
Some icons were taken from [ReShot](https://www.reshot.com) site and are licensed under Reshot Free License Some icons were taken from [ReShot](https://www.reshot.com) site and are licensed under Reshot Free License.
The program is completely free to use. The program is completely free to use.

@ -9,7 +9,7 @@ homepage = "https://github.com/qarmin/czkawka"
repository = "https://github.com/qarmin/czkawka" repository = "https://github.com/qarmin/czkawka"
[dependencies] [dependencies]
structopt = "0.3.26" clap = { version = "3.2.3", features = ["derive"]}
# For enum types # For enum types
image_hasher = "1.0.0" image_hasher = "1.0.0"

@ -1,254 +1,253 @@
use std::path::PathBuf; use std::path::PathBuf;
use image_hasher::{FilterType, HashAlg}; use image_hasher::{FilterType, HashAlg};
use structopt::StructOpt;
use czkawka_core::common_dir_traversal::CheckingMethod; use czkawka_core::common_dir_traversal::CheckingMethod;
use czkawka_core::duplicate::{DeleteMethod, HashType}; use czkawka_core::duplicate::{DeleteMethod, HashType};
use czkawka_core::same_music::MusicSimilarity; use czkawka_core::same_music::MusicSimilarity;
use czkawka_core::similar_images::SimilarityPreset; use czkawka_core::similar_images::SimilarityPreset;
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
#[structopt(name = "czkawka", help_message = HELP_MESSAGE, template = HELP_TEMPLATE)] #[clap(name = "czkawka", help_message = HELP_MESSAGE, template = HELP_TEMPLATE)]
pub enum Commands { pub enum Commands {
#[structopt(name = "dup", about = "Finds duplicate files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka dup -d /home/rafal -e /home/rafal/Obrazy -m 25 -x 7z rar IMAGE -s hash -f results.txt -D aeo")] #[clap(name = "dup", about = "Finds duplicate files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka dup -d /home/rafal -e /home/rafal/Obrazy -m 25 -x 7z rar IMAGE -s hash -f results.txt -D aeo")]
Duplicates { Duplicates {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "8192", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")] #[clap(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "8192", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")]
minimal_file_size: u64, minimal_file_size: u64,
#[structopt(short = "i", long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")] #[clap(short = 'i', long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")]
maximal_file_size: u64, maximal_file_size: u64,
#[structopt(short = "c", long, parse(try_from_str = parse_minimal_file_size), default_value = "257144", help = "Minimum cached file size in bytes", long_help = "Minimum size of cached files in bytes, assigning bigger value may speed up will cause that lower amount of files will be cached, but loading of cache will be faster")] #[clap(short = 'c', long, parse(try_from_str = parse_minimal_file_size), default_value = "257144", help = "Minimum cached file size in bytes", long_help = "Minimum size of cached files in bytes, assigning bigger value may speed up will cause that lower amount of files will be cached, but loading of cache will be faster")]
minimal_cached_file_size: u64, minimal_cached_file_size: u64,
#[structopt(flatten)] #[clap(flatten)]
allowed_extensions: AllowedExtensions, allowed_extensions: AllowedExtensions,
#[structopt(short, long, default_value = "HASH", parse(try_from_str = parse_checking_method), help = "Search method (NAME, SIZE, HASH)", long_help = "Methods to search files.\nNAME - Fast but but rarely usable,\nSIZE - Fast but not accurate, checking by the file's size,\nHASH - The slowest method, checking by the hash of the entire file")] #[clap(short, long, default_value = "HASH", parse(try_from_str = parse_checking_method), help = "Search method (NAME, SIZE, HASH)", long_help = "Methods to search files.\nNAME - Fast but but rarely usable,\nSIZE - Fast but not accurate, checking by the file's size,\nHASH - The slowest method, checking by the hash of the entire file")]
search_method: CheckingMethod, search_method: CheckingMethod,
#[structopt(short = "D", long, default_value = "NONE", parse(try_from_str = parse_delete_method), help = "Delete method (AEN, AEO, ON, OO, HARD)", long_help = "Methods to delete the files.\nAEN - All files except the newest,\nAEO - All files except the oldest,\nON - Only 1 file, the newest,\nOO - Only 1 file, the oldest\nHARD - create hard link\nNONE - not delete files")] #[clap(short = 'D', long, default_value = "NONE", parse(try_from_str = parse_delete_method), help = "Delete method (AEN, AEO, ON, OO, HARD)", long_help = "Methods to delete the files.\nAEN - All files except the newest,\nAEO - All files except the oldest,\nON - Only 1 file, the newest,\nOO - Only 1 file, the oldest\nHARD - create hard link\nNONE - not delete files")]
delete_method: DeleteMethod, delete_method: DeleteMethod,
#[structopt(short = "t", long, default_value = "BLAKE3", parse(try_from_str = parse_hash_type), help = "Hash type (BLAKE3, CRC32, XXH3)")] #[clap(short = 't', long, default_value = "BLAKE3", parse(try_from_str = parse_hash_type), help = "Hash type (BLAKE3, CRC32, XXH3)")]
hash_type: HashType, hash_type: HashType,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
#[structopt(flatten)] #[clap(flatten)]
allow_hard_links: AllowHardLinks, allow_hard_links: AllowHardLinks,
#[structopt(flatten)] #[clap(flatten)]
dryrun: DryRun, dryrun: DryRun,
}, },
#[structopt(name = "empty-folders", about = "Finds empty folders", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka empty-folders -d /home/rafal/rr /home/gateway -f results.txt")] #[clap(name = "empty-folders", about = "Finds empty folders", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka empty-folders -d /home/rafal/rr /home/gateway -f results.txt")]
EmptyFolders { EmptyFolders {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(short = "D", long, help = "Delete found folders")] #[clap(short = 'D', long, help = "Delete found folders")]
delete_folders: bool, delete_folders: bool,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
}, },
#[structopt(name = "big", about = "Finds big files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -x VIDEO -f results.txt")] #[clap(name = "big", about = "Finds big files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -x VIDEO -f results.txt")]
BiggestFiles { BiggestFiles {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(flatten)] #[clap(flatten)]
allowed_extensions: AllowedExtensions, allowed_extensions: AllowedExtensions,
#[structopt(short, long, default_value = "50", help = "Number of files to be shown")] #[clap(short, long, default_value = "50", help = "Number of files to be shown")]
number_of_files: usize, number_of_files: usize,
#[structopt(short = "D", long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
delete_files: bool, delete_files: bool,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
}, },
#[structopt(name = "empty-files", about = "Finds empty files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka empty-files -d /home/rafal /home/szczekacz -e /home/rafal/Pulpit -R -f results.txt")] #[clap(name = "empty-files", about = "Finds empty files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka empty-files -d /home/rafal /home/szczekacz -e /home/rafal/Pulpit -R -f results.txt")]
EmptyFiles { EmptyFiles {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(flatten)] #[clap(flatten)]
allowed_extensions: AllowedExtensions, allowed_extensions: AllowedExtensions,
#[structopt(short = "D", long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
delete_files: bool, delete_files: bool,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
}, },
#[structopt(name = "temp", about = "Finds temporary files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka temp -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt -D")] #[clap(name = "temp", about = "Finds temporary files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka temp -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt -D")]
Temporary { Temporary {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(short = "D", long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
delete_files: bool, delete_files: bool,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
}, },
#[structopt(name = "image", about = "Finds similar images", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka image -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt")] #[clap(name = "image", about = "Finds similar images", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka image -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt")]
SimilarImages { SimilarImages {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "16384", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")] #[clap(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "16384", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")]
minimal_file_size: u64, minimal_file_size: u64,
#[structopt(short = "i", long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")] #[clap(short = 'i', long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")]
maximal_file_size: u64, maximal_file_size: u64,
#[structopt(short, long, default_value = "High", parse(try_from_str = parse_similar_images_similarity), help = "Similairty level (Minimal, VerySmall, Small, Medium, High, VeryHigh)", long_help = "Methods to choose similarity level of images which will be considered as duplicated.")] #[clap(short, long, default_value = "High", parse(try_from_str = parse_similar_images_similarity), help = "Similairty level (Minimal, VerySmall, Small, Medium, High, VeryHigh)", long_help = "Methods to choose similarity level of images which will be considered as duplicated.")]
similarity_preset: SimilarityPreset, similarity_preset: SimilarityPreset,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
#[structopt(short = "g", long, default_value = "Gradient", parse(try_from_str = parse_similar_hash_algorithm), help = "Hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient)")] #[clap(short = 'g', long, default_value = "Gradient", parse(try_from_str = parse_similar_hash_algorithm), help = "Hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient)")]
hash_alg: HashAlg, hash_alg: HashAlg,
#[structopt(short = "z", long, default_value = "Lanczos3", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")] #[clap(short = 'z', long, default_value = "Lanczos3", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")]
image_filter: FilterType, image_filter: FilterType,
#[structopt(short = "c", long, default_value = "8", parse(try_from_str = parse_image_hash_size), help = "Hash size (allowed: 4, 8, 16)")] #[clap(short = 'c', long, default_value = "8", parse(try_from_str = parse_image_hash_size), help = "Hash size (allowed: 4, 8, 16)")]
hash_size: u8, hash_size: u8,
}, },
#[structopt(name = "music", about = "Finds same music by tags", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka music -d /home/rafal -f results.txt")] #[clap(name = "music", about = "Finds same music by tags", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka music -d /home/rafal -f results.txt")]
SameMusic { SameMusic {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
// #[structopt(short = "D", long, help = "Delete found files")] // #[clap(short = 'D', long, help = "Delete found files")]
// delete_files: bool, TODO // delete_files: bool, TODO
#[structopt(short = "z", long, default_value = "track_title,track_artist", parse(try_from_str = parse_music_duplicate_type), help = "Search method (track_title,track_artist,year,bitrate,genre,length))", long_help = "Sets which rows must be equal to set this files as duplicates(may be mixed, but must be divided by commas).")] #[clap(short = 'z', long, default_value = "track_title,track_artist", parse(try_from_str = parse_music_duplicate_type), help = "Search method (track_title,track_artist,year,bitrate,genre,length))", long_help = "Sets which rows must be equal to set this files as duplicates(may be mixed, but must be divided by commas).")]
music_similarity: MusicSimilarity, music_similarity: MusicSimilarity,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
#[structopt(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "8192", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")] #[clap(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "8192", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")]
minimal_file_size: u64, minimal_file_size: u64,
#[structopt(short = "i", long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")] #[clap(short = 'i', long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")]
maximal_file_size: u64, maximal_file_size: u64,
}, },
#[structopt(name = "symlinks", about = "Finds invalid symlinks", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka symlinks -d /home/kicikici/ /home/szczek -e /home/kicikici/jestempsem -x jpg -f results.txt")] #[clap(name = "symlinks", about = "Finds invalid symlinks", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka symlinks -d /home/kicikici/ /home/szczek -e /home/kicikici/jestempsem -x jpg -f results.txt")]
InvalidSymlinks { InvalidSymlinks {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(flatten)] #[clap(flatten)]
allowed_extensions: AllowedExtensions, allowed_extensions: AllowedExtensions,
#[structopt(short = "D", long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
delete_files: bool, delete_files: bool,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
}, },
#[structopt(name = "broken", about = "Finds broken files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka broken -d /home/kicikici/ /home/szczek -e /home/kicikici/jestempsem -x jpg -f results.txt")] #[clap(name = "broken", about = "Finds broken files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka broken -d /home/kicikici/ /home/szczek -e /home/kicikici/jestempsem -x jpg -f results.txt")]
BrokenFiles { BrokenFiles {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
#[structopt(flatten)] #[clap(flatten)]
allowed_extensions: AllowedExtensions, allowed_extensions: AllowedExtensions,
#[structopt(short = "D", long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
delete_files: bool, delete_files: bool,
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
}, },
#[structopt(name = "video", about = "Finds similar video files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka videos -d /home/rafal -f results.txt")] #[clap(name = "video", about = "Finds similar video files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka videos -d /home/rafal -f results.txt")]
SimilarVideos { SimilarVideos {
#[structopt(flatten)] #[clap(flatten)]
directories: Directories, directories: Directories,
#[structopt(flatten)] #[clap(flatten)]
excluded_directories: ExcludedDirectories, excluded_directories: ExcludedDirectories,
#[structopt(flatten)] #[clap(flatten)]
excluded_items: ExcludedItems, excluded_items: ExcludedItems,
// #[structopt(short = "D", long, help = "Delete found files")] // #[clap(short = 'D', long, help = "Delete found files")]
// delete_files: bool, TODO // delete_files: bool, TODO
#[structopt(flatten)] #[clap(flatten)]
file_to_save: FileToSave, file_to_save: FileToSave,
#[structopt(flatten)] #[clap(flatten)]
allowed_extensions: AllowedExtensions, allowed_extensions: AllowedExtensions,
#[structopt(flatten)] #[clap(flatten)]
not_recursive: NotRecursive, not_recursive: NotRecursive,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[structopt(flatten)] #[clap(flatten)]
exclude_other_filesystems: ExcludeOtherFilesystems, exclude_other_filesystems: ExcludeOtherFilesystems,
#[structopt(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "8192", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")] #[clap(short, long, parse(try_from_str = parse_minimal_file_size), default_value = "8192", help = "Minimum size in bytes", long_help = "Minimum size of checked files in bytes, assigning bigger value may speed up searching")]
minimal_file_size: u64, minimal_file_size: u64,
#[structopt(short = "i", long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")] #[clap(short = 'i', long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")]
maximal_file_size: u64, maximal_file_size: u64,
#[structopt(short = "t", long, parse(try_from_str = parse_tolerance), default_value = "10", help = "Video maximium difference (allowed values <0,20>)", long_help = "Maximum difference between video frames, bigger value means that videos can looks more and more different (allowed values <0,20>)")] #[clap(short = 't', long, parse(try_from_str = parse_tolerance), default_value = "10", help = "Video maximium difference (allowed values <0,20>)", long_help = "Maximum difference between video frames, bigger value means that videos can looks more and more different (allowed values <0,20>)")]
tolerance: i32, tolerance: i32,
}, },
#[structopt(name = "tester", about = "Contains various test", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka tests -i")] #[clap(name = "tester", about = "Contains various test", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka tests -i")]
Tester { Tester {
#[structopt(short = "i", long = "test_image", help = "Test speed of hashing provided test.jpg image with different filters and methods.")] #[clap(short = 'i', long = "test_image", help = "Test speed of hashing provided test.jpg image with different filters and methods.")]
test_image: bool, test_image: bool,
}, },
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct Directories { pub struct Directories {
#[structopt( #[clap(
short, short,
long, long,
parse(from_os_str), parse(from_os_str),
@ -259,9 +258,9 @@ pub struct Directories {
pub directories: Vec<PathBuf>, pub directories: Vec<PathBuf>,
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct ExcludedDirectories { pub struct ExcludedDirectories {
#[structopt( #[clap(
short, short,
long, long,
parse(from_os_str), parse(from_os_str),
@ -271,10 +270,10 @@ pub struct ExcludedDirectories {
pub excluded_directories: Vec<PathBuf>, pub excluded_directories: Vec<PathBuf>,
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct ExcludedItems { pub struct ExcludedItems {
#[structopt( #[clap(
short = "E", short = 'E',
long, long,
help = "Excluded item(s)", help = "Excluded item(s)",
long_help = "List of excluded item(s) which contains * wildcard(may be slow, so use -e where possible)" long_help = "List of excluded item(s) which contains * wildcard(may be slow, so use -e where possible)"
@ -282,10 +281,10 @@ pub struct ExcludedItems {
pub excluded_items: Vec<String>, pub excluded_items: Vec<String>,
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct AllowedExtensions { pub struct AllowedExtensions {
#[structopt( #[clap(
short = "x", short = 'x',
long, long,
help = "Allowed file extension(s)", help = "Allowed file extension(s)",
long_help = "List of checked files with provided extension(s). There are also helpful macros which allow to easy use a typical extensions like:\nIMAGE(\"jpg,kra,gif,png,bmp,tiff,hdr,svg\"),\nTEXT(\"txt,doc,docx,odt,rtf\"),\nVIDEO(\"mp4,flv,mkv,webm,vob,ogv,gifv,avi,mov,wmv,mpg,m4v,m4p,mpeg,3gp\") or\nMUSIC(\"mp3,flac,ogg,tta,wma,webm\")\n " long_help = "List of checked files with provided extension(s). There are also helpful macros which allow to easy use a typical extensions like:\nIMAGE(\"jpg,kra,gif,png,bmp,tiff,hdr,svg\"),\nTEXT(\"txt,doc,docx,odt,rtf\"),\nVIDEO(\"mp4,flv,mkv,webm,vob,ogv,gifv,avi,mov,wmv,mpg,m4v,m4p,mpeg,3gp\") or\nMUSIC(\"mp3,flac,ogg,tta,wma,webm\")\n "
@ -293,34 +292,34 @@ pub struct AllowedExtensions {
pub allowed_extensions: Vec<String>, pub allowed_extensions: Vec<String>,
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct NotRecursive { pub struct NotRecursive {
#[structopt(short = "R", long, help = "Prevents from recursive check of folders")] #[clap(short = 'R', long, help = "Prevents from recursive check of folders")]
pub not_recursive: bool, pub not_recursive: bool,
} }
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct ExcludeOtherFilesystems { pub struct ExcludeOtherFilesystems {
#[structopt(short = "X", long, help = "Exclude files on other filesystems")] #[clap(short = 'X', long, help = "Exclude files on other filesystems")]
pub exclude_other_filesystems: bool, pub exclude_other_filesystems: bool,
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct FileToSave { pub struct FileToSave {
#[structopt(short, long, value_name = "file-name", help = "Saves the results into the file")] #[clap(short, long, value_name = "file-name", help = "Saves the results into the file")]
pub file_to_save: Option<PathBuf>, pub file_to_save: Option<PathBuf>,
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct AllowHardLinks { pub struct AllowHardLinks {
#[structopt(short = "L", long, help = "Do not ignore hard links")] #[clap(short = 'L', long, help = "Do not ignore hard links")]
pub allow_hard_links: bool, pub allow_hard_links: bool,
} }
#[derive(Debug, StructOpt)] #[derive(Debug, clap::StructOpt)]
pub struct DryRun { pub struct DryRun {
#[structopt(long, help = "Do nothing and print the operation that would happen.")] #[clap(long, help = "Do nothing and print the operation that would happen.")]
pub dryrun: bool, pub dryrun: bool,
} }
@ -487,8 +486,8 @@ const HELP_TEMPLATE: &str = r#"
USAGE: USAGE:
{usage} [SCFLAGS] [SCOPTIONS] {usage} [SCFLAGS] [SCOPTIONS]
FLAGS: OPTIONS:
{flags} {options}
SUBCOMMANDS: SUBCOMMANDS:
{subcommands} {subcommands}

@ -1,9 +1,6 @@
#![allow(clippy::needless_late_init)] #![allow(clippy::needless_late_init)]
use std::process; use clap::Parser;
use structopt::StructOpt;
use commands::Commands; use commands::Commands;
#[allow(unused_imports)] // It is used in release for print_results(). #[allow(unused_imports)] // It is used in release for print_results().
use czkawka_core::common_traits::*; use czkawka_core::common_traits::*;
@ -21,6 +18,7 @@ use czkawka_core::{
similar_videos::SimilarVideos, similar_videos::SimilarVideos,
temporary::{self, Temporary}, temporary::{self, Temporary},
}; };
use std::process;
mod commands; mod commands;

@ -25,7 +25,7 @@ futures = "0.3.21"
directories-next = "2.0.0" directories-next = "2.0.0"
# For opening files # For opening files
open = "2.1.2" open = "3.0.1"
# To get image preview # To get image preview
image = "0.24.2" image = "0.24.2"

@ -10,34 +10,29 @@ const TRANSLATION_SITE: &str = "https://crwd.in/czkawka";
pub fn connect_about_buttons(gui_data: &GuiData) { pub fn connect_about_buttons(gui_data: &GuiData) {
let button_donation = gui_data.about.button_donation.clone(); let button_donation = gui_data.about.button_donation.clone();
button_donation.connect_clicked(move |_| { button_donation.connect_clicked(move |_| {
open::that_in_background(SPONSOR_SITE); if let Err(e) = open::that(SPONSOR_SITE) {
// TODO find way to handle errors when opening this sites println!("Failed to open sponsor site: {}, reason {}", SPONSOR_SITE, e)
// if let Err(e) = open::that(SPONSOR_SITE) { };
// println!("Failed to open sponsor site: {}, reason {}", SPONSOR_SITE, e)
// };
}); });
let button_instruction = gui_data.about.button_instruction.clone(); let button_instruction = gui_data.about.button_instruction.clone();
button_instruction.connect_clicked(move |_| { button_instruction.connect_clicked(move |_| {
open::that_in_background(INSTRUCTION_SITE); if let Err(e) = open::that(INSTRUCTION_SITE) {
// if let Err(e) = open::that(INSTRUCTION_SITE) { println!("Failed to open instruction site: {}, reason {}", INSTRUCTION_SITE, e)
// println!("Failed to open instruction site: {}, reason {}", INSTRUCTION_SITE, e) };
// };
}); });
let button_repository = gui_data.about.button_repository.clone(); let button_repository = gui_data.about.button_repository.clone();
button_repository.connect_clicked(move |_| { button_repository.connect_clicked(move |_| {
open::that_in_background(REPOSITORY_SITE); if let Err(e) = open::that(REPOSITORY_SITE) {
// if let Err(e) = open::that(REPOSITORY_SITE) { println!("Failed to open repository site: {}, reason {}", REPOSITORY_SITE, e)
// println!("Failed to open repository site: {}, reason {}", REPOSITORY_SITE, e) };
// };
}); });
let button_translation = gui_data.about.button_translation.clone(); let button_translation = gui_data.about.button_translation.clone();
button_translation.connect_clicked(move |_| { button_translation.connect_clicked(move |_| {
open::that_in_background(TRANSLATION_SITE); if let Err(e) = open::that(TRANSLATION_SITE) {
// if let Err(e) = open::that(TRANSLATION_SITE) { println!("Failed to open repository site: {}, reason {}", TRANSLATION_SITE, e)
// println!("Failed to open repository site: {}, reason {}", TRANSLATION_SITE, e) };
// };
}); });
} }

@ -73,7 +73,10 @@ pub fn connect_settings(gui_data: &GuiData) {
button_settings_open_cache_folder.connect_clicked(move |_| { button_settings_open_cache_folder.connect_clicked(move |_| {
if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") { if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") {
let cache_dir = proj_dirs.cache_dir(); let cache_dir = proj_dirs.cache_dir();
open::that_in_background(cache_dir);
if let Err(e) = open::that(&cache_dir) {
println!("Failed to open config folder {:?}, reason {}", cache_dir, e);
};
} }
}); });
} }
@ -83,7 +86,10 @@ pub fn connect_settings(gui_data: &GuiData) {
button_settings_open_settings_folder.connect_clicked(move |_| { button_settings_open_settings_folder.connect_clicked(move |_| {
if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") { if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") {
let config_dir = proj_dirs.config_dir(); let config_dir = proj_dirs.config_dir();
open::that_in_background(config_dir);
if let Err(e) = open::that(&config_dir) {
println!("Failed to open config folder {:?}, reason {}", config_dir, e);
};
} }
}); });
} }

@ -132,11 +132,9 @@ fn common_open_function(tree_view: &gtk4::TreeView, column_name: i32, column_pat
OpenMode::PathAndName => get_full_name_from_path_name(&path, &name), OpenMode::PathAndName => get_full_name_from_path_name(&path, &name),
}; };
open::that_in_background(&end_path); if let Err(e) = open::that(&end_path) {
println!("Failed to open file {}, reason {}", end_path, e);
// if let Err(e) = open::that(&end_path) { };
// println!("Failed to open {} - Error {}", end_path, e);
// }
} }
} }
@ -192,7 +190,9 @@ fn common_open_function_upper_directories(tree_view: &gtk4::TreeView, column_ful
for tree_path in selected_rows.iter().rev() { for tree_path in selected_rows.iter().rev() {
let full_path = tree_model.get::<String>(&tree_model.iter(tree_path).unwrap(), column_full_path); let full_path = tree_model.get::<String>(&tree_model.iter(tree_path).unwrap(), column_full_path);
open::that_in_background(&full_path); if let Err(e) = open::that(&full_path) {
println!("Failed to open file {}, reason {}", full_path, e);
};
} }
} }

@ -213,6 +213,7 @@ impl LoadSaveStruct {
self.loaded_items.insert(key, vec_string); self.loaded_items.insert(key, vec_string);
} }
//noinspection RsLift
pub fn open_save_file(&self, text_view_errors: &TextView, save_configuration: bool, manual_execution: bool) -> Option<(File, PathBuf)> { pub fn open_save_file(&self, text_view_errors: &TextView, save_configuration: bool, manual_execution: bool) -> Option<(File, PathBuf)> {
if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") { if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") {
// Lin: /home/username/.config/czkawka // Lin: /home/username/.config/czkawka

@ -0,0 +1,25 @@
[advisories]
vulnerability = "deny"
unmaintained = "warn"
yanked = "deny"
ignore = [
"RUSTSEC-2020-0071", # https://rustsec.org/advisories/RUSTSEC-2020-0071 - Potential segfault in the time crate.
]
[bans]
multiple-versions = "deny"
wildcards = "allow"
deny = []
skip = []
skip-tree = []
[licenses]
unlicensed = "allow"
allow-osi-fsf-free = "either"
copyleft = "allow"
allow = [
"MIT",
"Apache-2.0 WITH LLVM-exception",
]
Loading…
Cancel
Save