1
0
Fork 0
mirror of synced 2024-05-11 07:53:42 +12:00

Things dedup (#1183)

* Deduplicate cli settings

* Save

* Nice

* TODO even bigger generalization

* Simplification

* Bad
This commit is contained in:
Rafał Mikrut 2024-01-14 14:38:55 +01:00 committed by GitHub
parent 0defcbd253
commit 6cde5ab7a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 497 additions and 890 deletions

57
Cargo.lock generated
View file

@ -953,6 +953,19 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "const-field-offset" name = "const-field-offset"
version = "0.1.3" version = "0.1.3"
@ -1179,6 +1192,16 @@ dependencies = [
"syn 2.0.48", "syn 2.0.48",
] ]
[[package]]
name = "ctrlc"
version = "3.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
dependencies = [
"nix 0.27.1",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "cursor-icon" name = "cursor-icon"
version = "1.1.0" version = "1.1.0"
@ -1190,10 +1213,13 @@ name = "czkawka_cli"
version = "6.1.0" version = "6.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"crossbeam-channel",
"ctrlc",
"czkawka_core", "czkawka_core",
"fun_time", "fun_time",
"handsome_logger", "handsome_logger",
"image_hasher", "image_hasher",
"indicatif",
"log", "log",
] ]
@ -1574,6 +1600,12 @@ 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 = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.33" version = "0.8.33"
@ -3081,6 +3113,19 @@ dependencies = [
"hashbrown 0.14.3", "hashbrown 0.14.3",
] ]
[[package]]
name = "indicatif"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
dependencies = [
"console",
"instant",
"number_prefix",
"portable-atomic",
"unicode-width",
]
[[package]] [[package]]
name = "infer" name = "infer"
version = "0.15.0" version = "0.15.0"
@ -3898,6 +3943,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "number_prefix"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]] [[package]]
name = "objc" name = "objc"
version = "0.2.7" version = "0.2.7"
@ -6102,6 +6153,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94"
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"

View file

@ -10,6 +10,9 @@
### CLI ### CLI
- Providing full static rust binary with [Eyra](https://github.com/sunfishcode/eyra) - [#1102](https://github.com/qarmin/czkawka/pull/1102) - Providing full static rust binary with [Eyra](https://github.com/sunfishcode/eyra) - [#1102](https://github.com/qarmin/czkawka/pull/1102)
- Fixed duplicated `-c` argument, now saving as compact json is handled via `-C` - [#1153](https://github.com/qarmin/czkawka/pull/1153) - Fixed duplicated `-c` argument, now saving as compact json is handled via `-C` - [#1153](https://github.com/qarmin/czkawka/pull/1153)
- Added progress bar - [#TODO]()
- Clean and safe cancelling of scan - [#TODO]()
- Unification of CLI arguments - [#TODO]()
### Krokiet GUI ### Krokiet GUI
- Initial release of new gui - [#1102](https://github.com/qarmin/czkawka/pull/1102) - Initial release of new gui - [#1102](https://github.com/qarmin/czkawka/pull/1102)

View file

@ -19,6 +19,9 @@ log = "0.4.20"
handsome_logger = "0.8" handsome_logger = "0.8"
fun_time = { version = "0.3", features = ["log"] } fun_time = { version = "0.3", features = ["log"] }
czkawka_core = { path = "../czkawka_core", version = "6.1.0", features = [] } czkawka_core = { path = "../czkawka_core", version = "6.1.0", features = [] }
indicatif = "0.17"
crossbeam-channel = { version = "0.5", features = [] }
ctrlc = { version = "3.4", features = ["termination"] }
[features] [features]
default = [] default = []

View file

@ -87,13 +87,7 @@ pub enum Commands {
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct DuplicatesArgs { pub struct DuplicatesArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap( #[clap(
short, short,
long, long,
@ -121,8 +115,6 @@ pub struct DuplicatesArgs {
long_help = "Minimum size of cached files in bytes, assigning bigger value may speed up the scan but loading the cache will be slower, assigning smaller value may slow down the scan and some files may need to be hashed again but loading the cache will be faster" long_help = "Minimum size of cached files in bytes, assigning bigger value may speed up the scan but loading the cache will be slower, assigning smaller value may slow down the scan and some files may need to be hashed again but loading the cache will be faster"
)] )]
pub minimal_cached_file_size: u64, pub minimal_cached_file_size: u64,
#[clap(flatten)]
pub allowed_extensions: AllowedExtensions,
#[clap( #[clap(
short, short,
long, long,
@ -143,18 +135,7 @@ pub struct DuplicatesArgs {
)] )]
pub hash_type: HashType, pub hash_type: HashType,
#[clap(flatten)] #[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[clap(flatten)]
pub case_sensitive_name_comparison: CaseSensitiveNameComparison, pub case_sensitive_name_comparison: CaseSensitiveNameComparison,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
#[clap(flatten)] #[clap(flatten)]
pub allow_hard_links: AllowHardLinks, pub allow_hard_links: AllowHardLinks,
#[clap(flatten)] #[clap(flatten)]
@ -164,117 +145,43 @@ pub struct DuplicatesArgs {
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct EmptyFoldersArgs { pub struct EmptyFoldersArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(short = 'D', long, help = "Delete found folders")] #[clap(short = 'D', long, help = "Delete found folders")]
pub delete_folders: bool, pub delete_folders: bool,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
} }
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct BiggestFilesArgs { pub struct BiggestFilesArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(flatten)]
pub allowed_extensions: AllowedExtensions,
#[clap(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")]
pub number_of_files: usize, pub number_of_files: usize,
#[clap(short = 'D', long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
pub delete_files: bool, pub delete_files: bool,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[clap(short = 'J', long, help = "Finds the smallest files instead the biggest")] #[clap(short = 'J', long, help = "Finds the smallest files instead the biggest")]
pub smallest_mode: bool, pub smallest_mode: bool,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
} }
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct EmptyFilesArgs { pub struct EmptyFilesArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(flatten)]
pub allowed_extensions: AllowedExtensions,
#[clap(short = 'D', long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
pub delete_files: bool, pub delete_files: bool,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
} }
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct TemporaryArgs { pub struct TemporaryArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(short = 'D', long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
pub delete_files: bool, pub delete_files: bool,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
} }
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct SimilarImagesArgs { pub struct SimilarImagesArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap( #[clap(
short, short,
long, long,
@ -303,22 +210,9 @@ pub struct SimilarImagesArgs {
)] )]
pub similarity_preset: SimilarityPreset, pub similarity_preset: SimilarityPreset,
#[clap(flatten)] #[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub delete_method: DMethod, pub delete_method: DMethod,
#[clap(flatten)] #[clap(flatten)]
pub dry_run: DryRun, pub dry_run: DryRun,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
#[clap( #[clap(
short = 'g', short = 'g',
long, long,
@ -348,13 +242,7 @@ pub struct SimilarImagesArgs {
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct SameMusicArgs { pub struct SameMusicArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(flatten)] #[clap(flatten)]
pub delete_method: DMethod, pub delete_method: DMethod,
#[clap(flatten)] #[clap(flatten)]
@ -377,17 +265,6 @@ pub struct SameMusicArgs {
long_help = "Methods to search files.\nCONTENT - finds similar audio files by content, TAGS - finds similar images by tags, needs to set" long_help = "Methods to search files.\nCONTENT - finds similar audio files by content, TAGS - finds similar images by tags, needs to set"
)] )]
pub search_method: CheckingMethod, pub search_method: CheckingMethod,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
#[clap( #[clap(
short, short,
long, long,
@ -458,84 +335,27 @@ fn parse_minimum_segment_duration(src: &str) -> Result<f32, String> {
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct InvalidSymlinksArgs { pub struct InvalidSymlinksArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(flatten)]
pub allowed_extensions: AllowedExtensions,
#[clap(short = 'D', long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
pub delete_files: bool, pub delete_files: bool,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
} }
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct BrokenFilesArgs { pub struct BrokenFilesArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(flatten)]
pub allowed_extensions: AllowedExtensions,
#[clap(short = 'D', long, help = "Delete found files")] #[clap(short = 'D', long, help = "Delete found files")]
pub delete_files: bool, pub delete_files: bool,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
} }
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct SimilarVideosArgs { pub struct SimilarVideosArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)]
pub directories: Directories,
#[clap(flatten)]
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
#[clap(flatten)] #[clap(flatten)]
pub delete_method: DMethod, pub delete_method: DMethod,
#[clap(flatten)] #[clap(flatten)]
pub dry_run: DryRun, pub dry_run: DryRun,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)]
pub allowed_extensions: AllowedExtensions,
#[clap(flatten)]
pub not_recursive: NotRecursive,
#[cfg(target_family = "unix")]
#[clap(flatten)]
pub exclude_other_filesystems: ExcludeOtherFilesystems,
#[clap( #[clap(
short, short,
long, long,
@ -568,26 +388,53 @@ pub struct SimilarVideosArgs {
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct BadExtensionsArgs { pub struct BadExtensionsArgs {
#[clap(flatten)] #[clap(flatten)]
pub thread_number: ThreadNumber, pub common_cli_items: CommonCliItems,
#[clap(flatten)] }
pub directories: Directories,
#[clap(flatten)] #[derive(Debug, clap::Args)]
pub excluded_directories: ExcludedDirectories, pub struct CommonCliItems {
#[clap(flatten)] #[clap(short = 'T', long, default_value = "0", help = "Limits thread number, 0(default) will use all available threads")]
pub excluded_items: ExcludedItems, pub thread_number: usize,
#[clap(flatten)] #[clap(
pub allowed_extensions: AllowedExtensions, short,
long,
required = true,
help = "Directorie(s) to search",
long_help = "List of directorie(s) which will be searched(absolute path)"
)]
pub directories: Vec<PathBuf>,
#[clap(
short,
long,
help = "Excluded directorie(s)",
long_help = "List of directorie(s) which will be excluded from search(absolute path)"
)]
pub excluded_directories: Vec<PathBuf>,
#[clap(
short = 'E',
long,
help = "Excluded item(s)",
long_help = "List of excluded item(s) which contains * wildcard(may be slow, so use -e where possible)"
)]
pub excluded_items: Vec<String>,
#[clap(
short = 'x',
long,
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 "
)]
pub allowed_extensions: Vec<String>,
#[clap(flatten)] #[clap(flatten)]
pub file_to_save: FileToSave, pub file_to_save: FileToSave,
#[clap(flatten)] #[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave, pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)] #[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave, pub json_pretty_file_to_save: JsonPrettyFileToSave,
#[clap(flatten)] #[clap(short = 'R', long, help = "Prevents from recursive check of folders")]
pub not_recursive: NotRecursive, pub not_recursive: bool,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
#[clap(flatten)] #[clap(short = 'X', long, help = "Exclude files on other filesystems")]
pub exclude_other_filesystems: ExcludeOtherFilesystems, pub exclude_other_filesystems: bool,
} }
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
@ -603,70 +450,6 @@ pub struct DMethod {
pub delete_method: DeleteMethod, pub delete_method: DeleteMethod,
} }
#[derive(Debug, clap::Args)]
pub struct Directories {
#[clap(
short,
long,
required = true,
help = "Directorie(s) to search",
long_help = "List of directorie(s) which will be searched(absolute path)"
)]
pub directories: Vec<PathBuf>,
}
#[derive(Debug, clap::Args)]
pub struct ExcludedDirectories {
#[clap(
short,
long,
help = "Excluded directorie(s)",
long_help = "List of directorie(s) which will be excluded from search(absolute path)"
)]
pub excluded_directories: Vec<PathBuf>,
}
#[derive(Debug, clap::Args)]
pub struct ExcludedItems {
#[clap(
short = 'E',
long,
help = "Excluded item(s)",
long_help = "List of excluded item(s) which contains * wildcard(may be slow, so use -e where possible)"
)]
pub excluded_items: Vec<String>,
}
#[derive(Debug, clap::Args)]
pub struct AllowedExtensions {
#[clap(
short = 'x',
long,
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 "
)]
pub allowed_extensions: Vec<String>,
}
#[derive(Debug, clap::Args)]
pub struct NotRecursive {
#[clap(short = 'R', long, help = "Prevents from recursive check of folders")]
pub not_recursive: bool,
}
#[derive(Debug, clap::Args)]
pub struct ThreadNumber {
#[clap(short = 'T', long, default_value = "0", help = "Limits thread number, 0(default) will use all available threads")]
pub thread_number: usize,
}
#[cfg(target_family = "unix")]
#[derive(Debug, clap::Args)]
pub struct ExcludeOtherFilesystems {
#[clap(short = 'X', long, help = "Exclude files on other filesystems")]
pub exclude_other_filesystems: bool,
}
#[derive(Debug, clap::Args)] #[derive(Debug, clap::Args)]
pub struct FileToSave { pub struct FileToSave {
#[clap(short, long, value_name = "file-name", help = "Saves the results into the formatted txt file")] #[clap(short, long, value_name = "file-name", help = "Saves the results into the formatted txt file")]

View file

@ -1,6 +1,9 @@
#![allow(clippy::needless_late_init)] #![allow(clippy::needless_late_init)]
use std::thread;
use clap::Parser; use clap::Parser;
use crossbeam_channel::{bounded, unbounded, Receiver, Sender};
use log::error; use log::error;
use commands::Commands; use commands::Commands;
@ -8,6 +11,7 @@ use czkawka_core::bad_extensions::BadExtensions;
use czkawka_core::big_file::{BigFile, SearchMode}; use czkawka_core::big_file::{BigFile, SearchMode};
use czkawka_core::broken_files::BrokenFiles; use czkawka_core::broken_files::BrokenFiles;
use czkawka_core::common::{print_version_mode, set_number_of_threads, setup_logger}; use czkawka_core::common::{print_version_mode, set_number_of_threads, setup_logger};
use czkawka_core::common_dir_traversal::ProgressData;
use czkawka_core::common_tool::{CommonData, DeleteMethod}; use czkawka_core::common_tool::{CommonData, DeleteMethod};
#[allow(unused_imports)] // It is used in release for print_results_to_output(). #[allow(unused_imports)] // It is used in release for print_results_to_output().
use czkawka_core::common_traits::*; use czkawka_core::common_traits::*;
@ -21,11 +25,13 @@ use czkawka_core::similar_videos::SimilarVideos;
use czkawka_core::temporary::Temporary; use czkawka_core::temporary::Temporary;
use crate::commands::{ use crate::commands::{
Args, BadExtensionsArgs, BiggestFilesArgs, BrokenFilesArgs, DuplicatesArgs, EmptyFilesArgs, EmptyFoldersArgs, InvalidSymlinksArgs, SameMusicArgs, SimilarImagesArgs, Args, BadExtensionsArgs, BiggestFilesArgs, BrokenFilesArgs, CommonCliItems, DuplicatesArgs, EmptyFilesArgs, EmptyFoldersArgs, InvalidSymlinksArgs, SameMusicArgs,
SimilarVideosArgs, TemporaryArgs, SimilarImagesArgs, SimilarVideosArgs, TemporaryArgs,
}; };
use crate::progress::connect_progress;
mod commands; mod commands;
mod progress;
fn main() { fn main() {
let command = Args::parse().command; let command = Args::parse().command;
@ -37,146 +43,95 @@ fn main() {
println!("{command:?}"); println!("{command:?}");
} }
match command { let (progress_sender, progress_receiver): (Sender<ProgressData>, Receiver<ProgressData>) = unbounded();
Commands::Duplicates(duplicates_args) => duplicates(duplicates_args), let (stop_sender, stop_receiver): (Sender<()>, Receiver<()>) = bounded(1);
Commands::EmptyFolders(empty_folders_args) => empty_folders(empty_folders_args),
Commands::BiggestFiles(biggest_files_args) => biggest_files(biggest_files_args), let calculate_thread = thread::spawn(move || match command {
Commands::EmptyFiles(empty_files_args) => empty_files(empty_files_args), Commands::Duplicates(duplicates_args) => duplicates(duplicates_args, &stop_receiver, &progress_sender),
Commands::Temporary(temporary_args) => temporary(temporary_args), Commands::EmptyFolders(empty_folders_args) => empty_folders(empty_folders_args, &stop_receiver, &progress_sender),
Commands::SimilarImages(similar_images_args) => similar_images(similar_images_args), Commands::BiggestFiles(biggest_files_args) => biggest_files(biggest_files_args, &stop_receiver, &progress_sender),
Commands::SameMusic(same_music_args) => same_music(same_music_args), Commands::EmptyFiles(empty_files_args) => empty_files(empty_files_args, &stop_receiver, &progress_sender),
Commands::InvalidSymlinks(invalid_symlinks_args) => invalid_symlinks(invalid_symlinks_args), Commands::Temporary(temporary_args) => temporary(temporary_args, &stop_receiver, &progress_sender),
Commands::BrokenFiles(broken_files_args) => broken_files(broken_files_args), Commands::SimilarImages(similar_images_args) => similar_images(similar_images_args, &stop_receiver, &progress_sender),
Commands::SimilarVideos(similar_videos_args) => similar_videos(similar_videos_args), Commands::SameMusic(same_music_args) => same_music(same_music_args, &stop_receiver, &progress_sender),
Commands::BadExtensions(bad_extensions_args) => bad_extensions(bad_extensions_args), Commands::InvalidSymlinks(invalid_symlinks_args) => invalid_symlinks(invalid_symlinks_args, &stop_receiver, &progress_sender),
Commands::BrokenFiles(broken_files_args) => broken_files(broken_files_args, &stop_receiver, &progress_sender),
Commands::SimilarVideos(similar_videos_args) => similar_videos(similar_videos_args, &stop_receiver, &progress_sender),
Commands::BadExtensions(bad_extensions_args) => bad_extensions(bad_extensions_args, &stop_receiver, &progress_sender),
Commands::Tester {} => { Commands::Tester {} => {
test_image_conversion_speed(); test_image_conversion_speed();
} }
} });
ctrlc::set_handler(move || {
println!("Get Sender");
stop_sender.send(()).expect("Could not send signal on channel.");
})
.expect("Error setting Ctrl-C handler");
connect_progress(&progress_receiver);
calculate_thread.join().unwrap();
} }
fn duplicates(duplicates: DuplicatesArgs) { fn duplicates(duplicates: DuplicatesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let DuplicatesArgs { let DuplicatesArgs {
thread_number, common_cli_items,
directories,
excluded_directories,
excluded_items,
minimal_file_size, minimal_file_size,
maximal_file_size, maximal_file_size,
minimal_cached_file_size, minimal_cached_file_size,
allowed_extensions,
search_method, search_method,
delete_method, delete_method,
hash_type, hash_type,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
allow_hard_links, allow_hard_links,
dry_run, dry_run,
case_sensitive_name_comparison, case_sensitive_name_comparison,
} = duplicates; } = duplicates;
set_number_of_threads(thread_number.thread_number);
let mut item = DuplicateFinder::new(); let mut item = DuplicateFinder::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_minimal_file_size(minimal_file_size); item.set_minimal_file_size(minimal_file_size);
item.set_maximal_file_size(maximal_file_size); item.set_maximal_file_size(maximal_file_size);
item.set_minimal_cache_file_size(minimal_cached_file_size); item.set_minimal_cache_file_size(minimal_cached_file_size);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_check_method(search_method); item.set_check_method(search_method);
item.set_delete_method(delete_method.delete_method); item.set_delete_method(delete_method.delete_method);
item.set_hash_type(hash_type); item.set_hash_type(hash_type);
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.set_ignore_hard_links(!allow_hard_links.allow_hard_links); item.set_ignore_hard_links(!allow_hard_links.allow_hard_links);
item.set_dry_run(dry_run.dry_run); item.set_dry_run(dry_run.dry_run);
item.set_case_sensitive_name_comparison(case_sensitive_name_comparison.case_sensitive_name_comparison); item.set_case_sensitive_name_comparison(case_sensitive_name_comparison.case_sensitive_name_comparison);
item.find_duplicates(None, None); item.find_duplicates(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn empty_folders(empty_folders: EmptyFoldersArgs) { fn empty_folders(empty_folders: EmptyFoldersArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let EmptyFoldersArgs { let EmptyFoldersArgs { common_cli_items, delete_folders } = empty_folders;
thread_number,
directories,
delete_folders,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
excluded_directories,
excluded_items,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
} = empty_folders;
set_number_of_threads(thread_number.thread_number);
let mut item = EmptyFolder::new(); let mut item = EmptyFolder::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
if delete_folders { if delete_folders {
item.set_delete_method(DeleteMethod::Delete); item.set_delete_method(DeleteMethod::Delete);
} }
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.find_empty_folders(None, None); item.find_empty_folders(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn biggest_files(biggest_files: BiggestFilesArgs) { fn biggest_files(biggest_files: BiggestFilesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let BiggestFilesArgs { let BiggestFilesArgs {
thread_number, common_cli_items,
directories,
excluded_directories,
excluded_items,
allowed_extensions,
number_of_files, number_of_files,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
delete_files, delete_files,
smallest_mode, smallest_mode,
} = biggest_files; } = biggest_files;
set_number_of_threads(thread_number.thread_number);
let mut item = BigFile::new(); let mut item = BigFile::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_number_of_files_to_check(number_of_files); item.set_number_of_files_to_check(number_of_files);
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
if delete_files { if delete_files {
item.set_delete_method(DeleteMethod::Delete); item.set_delete_method(DeleteMethod::Delete);
} }
@ -184,113 +139,47 @@ fn biggest_files(biggest_files: BiggestFilesArgs) {
item.set_search_mode(SearchMode::SmallestFiles); item.set_search_mode(SearchMode::SmallestFiles);
} }
item.find_big_files(None, None); item.find_big_files(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn empty_files(empty_files: EmptyFilesArgs) { fn empty_files(empty_files: EmptyFilesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let EmptyFilesArgs { let EmptyFilesArgs { common_cli_items, delete_files } = empty_files;
thread_number,
directories,
excluded_directories,
excluded_items,
allowed_extensions,
delete_files,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
} = empty_files;
set_number_of_threads(thread_number.thread_number);
let mut item = EmptyFiles::new(); let mut item = EmptyFiles::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
if delete_files { if delete_files {
item.set_delete_method(DeleteMethod::Delete); item.set_delete_method(DeleteMethod::Delete);
} }
item.find_empty_files(None, None); item.find_empty_files(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn temporary(temporary: TemporaryArgs) { fn temporary(temporary: TemporaryArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let TemporaryArgs { let TemporaryArgs { common_cli_items, delete_files } = temporary;
thread_number,
directories,
excluded_directories,
excluded_items,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
delete_files,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
} = temporary;
set_number_of_threads(thread_number.thread_number);
let mut item = Temporary::new(); let mut item = Temporary::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
if delete_files { if delete_files {
item.set_delete_method(DeleteMethod::Delete); item.set_delete_method(DeleteMethod::Delete);
} }
item.find_temporary_files(None, None); item.find_temporary_files(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn similar_images(similar_images: SimilarImagesArgs) { fn similar_images(similar_images: SimilarImagesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let SimilarImagesArgs { let SimilarImagesArgs {
thread_number, common_cli_items,
directories,
excluded_directories,
excluded_items,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
minimal_file_size, minimal_file_size,
maximal_file_size, maximal_file_size,
similarity_preset, similarity_preset,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
hash_alg, hash_alg,
image_filter, image_filter,
hash_size, hash_size,
@ -298,49 +187,27 @@ fn similar_images(similar_images: SimilarImagesArgs) {
dry_run, dry_run,
} = similar_images; } = similar_images;
set_number_of_threads(thread_number.thread_number);
let mut item = SimilarImages::new(); let mut item = SimilarImages::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_minimal_file_size(minimal_file_size); item.set_minimal_file_size(minimal_file_size);
item.set_maximal_file_size(maximal_file_size); item.set_maximal_file_size(maximal_file_size);
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.set_image_filter(image_filter); item.set_image_filter(image_filter);
item.set_hash_alg(hash_alg); item.set_hash_alg(hash_alg);
item.set_hash_size(hash_size); item.set_hash_size(hash_size);
item.set_delete_method(delete_method.delete_method); item.set_delete_method(delete_method.delete_method);
item.set_dry_run(dry_run.dry_run); item.set_dry_run(dry_run.dry_run);
item.set_similarity(return_similarity_from_similarity_preset(&similarity_preset, hash_size)); item.set_similarity(return_similarity_from_similarity_preset(&similarity_preset, hash_size));
item.find_similar_images(None, None); item.find_similar_images(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn same_music(same_music: SameMusicArgs) { fn same_music(same_music: SameMusicArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let SameMusicArgs { let SameMusicArgs {
thread_number, common_cli_items,
directories,
excluded_directories,
excluded_items,
delete_method, delete_method,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
minimal_file_size, minimal_file_size,
maximal_file_size, maximal_file_size,
music_similarity, music_similarity,
@ -350,18 +217,11 @@ fn same_music(same_music: SameMusicArgs) {
search_method, search_method,
} = same_music; } = same_music;
set_number_of_threads(thread_number.thread_number);
let mut item = SameMusic::new(); let mut item = SameMusic::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_minimal_file_size(minimal_file_size); item.set_minimal_file_size(minimal_file_size);
item.set_maximal_file_size(maximal_file_size); item.set_maximal_file_size(maximal_file_size);
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.set_music_similarity(music_similarity); item.set_music_similarity(music_similarity);
item.set_delete_method(delete_method.delete_method); item.set_delete_method(delete_method.delete_method);
item.set_dry_run(dry_run.dry_run); item.set_dry_run(dry_run.dry_run);
@ -369,197 +229,111 @@ fn same_music(same_music: SameMusicArgs) {
item.set_maximum_difference(maximum_difference); item.set_maximum_difference(maximum_difference);
item.set_check_type(search_method); item.set_check_type(search_method);
item.find_same_music(None, None); item.find_same_music(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs) { fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let InvalidSymlinksArgs { let InvalidSymlinksArgs { common_cli_items, delete_files } = invalid_symlinks;
thread_number,
directories,
excluded_directories,
excluded_items,
allowed_extensions,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
delete_files,
} = invalid_symlinks;
set_number_of_threads(thread_number.thread_number);
let mut item = InvalidSymlinks::new(); let mut item = InvalidSymlinks::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
if delete_files { if delete_files {
item.set_delete_method(DeleteMethod::Delete); item.set_delete_method(DeleteMethod::Delete);
} }
item.find_invalid_links(None, None); item.find_invalid_links(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn broken_files(broken_files: BrokenFilesArgs) { fn broken_files(broken_files: BrokenFilesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let BrokenFilesArgs { let BrokenFilesArgs { common_cli_items, delete_files } = broken_files;
thread_number,
directories,
excluded_directories,
excluded_items,
allowed_extensions,
delete_files,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
} = broken_files;
set_number_of_threads(thread_number.thread_number);
let mut item = BrokenFiles::new(); let mut item = BrokenFiles::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
if delete_files { if delete_files {
item.set_delete_method(DeleteMethod::Delete); item.set_delete_method(DeleteMethod::Delete);
} }
item.find_broken_files(None, None); item.find_broken_files(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn similar_videos(similar_videos: SimilarVideosArgs) { fn similar_videos(similar_videos: SimilarVideosArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let SimilarVideosArgs { let SimilarVideosArgs {
thread_number, common_cli_items,
directories,
excluded_directories,
excluded_items,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
tolerance, tolerance,
minimal_file_size, minimal_file_size,
maximal_file_size, maximal_file_size,
allowed_extensions,
delete_method, delete_method,
dry_run, dry_run,
} = similar_videos; } = similar_videos;
set_number_of_threads(thread_number.thread_number);
let mut item = SimilarVideos::new(); let mut item = SimilarVideos::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.set_minimal_file_size(minimal_file_size); item.set_minimal_file_size(minimal_file_size);
item.set_maximal_file_size(maximal_file_size); item.set_maximal_file_size(maximal_file_size);
item.set_tolerance(tolerance); item.set_tolerance(tolerance);
item.set_delete_method(delete_method.delete_method); item.set_delete_method(delete_method.delete_method);
item.set_dry_run(dry_run.dry_run); item.set_dry_run(dry_run.dry_run);
item.find_similar_videos(None, None); item.find_similar_videos(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn bad_extensions(bad_extensions: BadExtensionsArgs) { fn bad_extensions(bad_extensions: BadExtensionsArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender<ProgressData>) {
let BadExtensionsArgs { let BadExtensionsArgs { common_cli_items } = bad_extensions;
thread_number,
directories,
excluded_directories,
excluded_items,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
not_recursive,
#[cfg(target_family = "unix")]
exclude_other_filesystems,
allowed_extensions,
} = bad_extensions;
set_number_of_threads(thread_number.thread_number);
let mut item = BadExtensions::new(); let mut item = BadExtensions::new();
item.set_included_directory(directories.directories); set_common_settings(&mut item, &common_cli_items);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.find_bad_extensions_files(None, None); item.find_bad_extensions_files(Some(stop_receiver), Some(progress_sender));
save_results_to_files(file_to_save.file_name(), json_compact_file_to_save.file_name(), json_pretty_file_to_save.file_name(), &item); save_and_print_results(&mut item, &common_cli_items);
if !cfg!(debug_assertions) {
item.print_results_to_output();
}
item.get_text_messages().print_messages();
} }
fn save_results_to_files<T: PrintResults>(txt_file_name: Option<&str>, compact_json_file_name: Option<&str>, pretty_json_file_name: Option<&str>, item: &T) { fn save_and_print_results<T: CommonData + PrintResults>(component: &mut T, common_cli_items: &CommonCliItems) {
if let Some(file_name) = txt_file_name { if let Some(file_name) = common_cli_items.file_to_save.file_name() {
if let Err(e) = item.print_results_to_file(file_name) { if let Err(e) = component.print_results_to_file(file_name) {
error!("Failed to save results to file {e}"); error!("Failed to save results to file {e}");
} }
} }
if let Some(file_name) = compact_json_file_name { if let Some(file_name) = common_cli_items.json_compact_file_to_save.file_name() {
if let Err(e) = item.save_results_to_file_as_json(file_name, false) { if let Err(e) = component.save_results_to_file_as_json(file_name, false) {
error!("Failed to save compact json results to file {e}"); error!("Failed to save compact json results to file {e}");
} }
} }
if let Some(file_name) = pretty_json_file_name { if let Some(file_name) = common_cli_items.json_pretty_file_to_save.file_name() {
if let Err(e) = item.save_results_to_file_as_json(file_name, true) { if let Err(e) = component.save_results_to_file_as_json(file_name, true) {
error!("Failed to save pretty json results to file {e}"); error!("Failed to save pretty json results to file {e}");
} }
} }
if !cfg!(debug_assertions) {
component.print_results_to_output();
}
component.get_text_messages().print_messages();
}
fn set_common_settings<T>(component: &mut T, common_cli_items: &CommonCliItems)
where
T: CommonData + PrintResults,
{
set_number_of_threads(common_cli_items.thread_number);
component.set_included_directory(common_cli_items.directories.clone());
component.set_excluded_directory(common_cli_items.excluded_directories.clone());
component.set_excluded_items(common_cli_items.excluded_items.clone());
component.set_recursive_search(!common_cli_items.not_recursive);
#[cfg(target_family = "unix")]
component.set_exclude_other_filesystems(common_cli_items.exclude_other_filesystems);
component.set_allowed_extensions(common_cli_items.allowed_extensions.clone().join(","));
} }

View file

@ -0,0 +1,93 @@
use std::time::Duration;
use crossbeam_channel::Receiver;
use indicatif::{ProgressBar, ProgressStyle};
use czkawka_core::common_dir_traversal::{CheckingMethod, ProgressData, ToolType};
pub fn connect_progress(progress_receiver: &Receiver<ProgressData>) {
let mut pb = ProgressBar::new(1);
let mut latest_id = None;
while let Ok(progress_data) = progress_receiver.recv() {
if latest_id != Some(progress_data.current_stage) {
pb.finish_and_clear();
if progress_data.current_stage == 0 {
pb = get_progress_bar_for_collect_files();
} else if check_if_saving_cache(&progress_data) || check_if_loading_cache(&progress_data) {
pb = get_progress_loading_saving_cache(check_if_loading_cache(&progress_data));
} else {
pb = get_progress_known_values(progress_data.entries_to_check, &get_progress_message(&progress_data));
}
latest_id = Some(progress_data.current_stage);
}
pb.set_position(progress_data.entries_checked as u64);
if progress_data.current_stage == 0 && progress_data.tool_type != ToolType::EmptyFolders {
pb.set_message(format!("Collecting files: {}", progress_data.entries_checked));
} else if progress_data.current_stage == 0 {
pb.set_message(format!("Collecting folders: {}", progress_data.entries_checked));
}
}
pb.finish();
}
pub fn get_progress_message(progress_data: &ProgressData) -> String {
match (progress_data.tool_type, progress_data.current_stage, progress_data.checking_method) {
(ToolType::SameMusic, 2, CheckingMethod::AudioTags) | (ToolType::SameMusic, 5, CheckingMethod::AudioContent) => "Reading tags",
(ToolType::SameMusic, 2, CheckingMethod::AudioContent) => "Calculating fingerprint",
(ToolType::SameMusic, 4, CheckingMethod::AudioTags) => "Comparing tags",
(ToolType::SameMusic, 4, CheckingMethod::AudioContent) => "Comparing fingerprint",
(ToolType::Duplicate, 2, CheckingMethod::Hash) => "Reading prehashes",
(ToolType::Duplicate, 5, CheckingMethod::Hash) => "Reading hashes",
(ToolType::SimilarImages, 1, _) => "Reading images",
(ToolType::SimilarImages, 2, _) => "Comparing image hashes",
(ToolType::SimilarVideos, 1, _) => "Reading similar values",
(ToolType::BrokenFiles, 1, _) => "Checking broken files",
(ToolType::BadExtensions, 1, _) => "Checking extensions of files",
_ => unreachable!(),
}
.to_string()
}
pub fn check_if_loading_cache(progress_data: &ProgressData) -> bool {
matches!(
(progress_data.tool_type, progress_data.current_stage),
(ToolType::SameMusic, 1) | (ToolType::Duplicate, 1 | 4)
)
}
pub fn check_if_saving_cache(progress_data: &ProgressData) -> bool {
matches!(
(progress_data.tool_type, progress_data.current_stage),
(ToolType::SameMusic, 3) | (ToolType::Duplicate, 3 | 6)
)
}
pub fn get_progress_bar_for_collect_files() -> ProgressBar {
let pb = ProgressBar::new_spinner();
pb.enable_steady_tick(Duration::from_millis(120));
pb.set_style(
ProgressStyle::with_template("{msg} {spinner:.blue}")
.unwrap()
.tick_strings(&["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸", "▪▪▪▪▪"]),
);
pb
}
pub fn get_progress_known_values(max_value: usize, msg: &str) -> ProgressBar {
let pb = ProgressBar::new(max_value as u64);
pb.set_style(ProgressStyle::with_template(&format!("{msg} [{{bar}}] {{pos}}/{{len}} ")).unwrap().progress_chars("=> "));
pb
}
pub fn get_progress_loading_saving_cache(loading: bool) -> ProgressBar {
let msg = if loading { "Loading cache" } else { "Saving cache" };
let pb = ProgressBar::new_spinner();
pb.enable_steady_tick(Duration::from_millis(120));
pb.set_style(
ProgressStyle::with_template(&format!("{msg} {{spinner:.blue}}"))
.unwrap()
.tick_strings(&["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸", "▪▪▪▪▪"]),
);
pb
}

View file

@ -156,17 +156,17 @@ impl BrokenFiles {
match result { match result {
DirTraversalResult::SuccessFiles { grouped_file_entries, warnings } => { DirTraversalResult::SuccessFiles { grouped_file_entries, warnings } => {
self.broken_files = grouped_file_entries self.files_to_check = grouped_file_entries
.into_values() .into_values()
.flatten() .flatten()
.map(|fe| { .map(|fe| {
let mut broken_entry = fe.into_broken_entry(); let mut broken_entry = fe.into_broken_entry();
broken_entry.type_of_file = check_extension_availability(broken_entry.get_path(), &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions); broken_entry.type_of_file = check_extension_availability(broken_entry.get_path(), &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions);
broken_entry (broken_entry.path.to_string_lossy().to_string(), broken_entry)
}) })
.collect(); .collect();
self.common_data.text_messages.warnings.extend(warnings); self.common_data.text_messages.warnings.extend(warnings);
debug!("check_files - Found {} image files.", self.broken_files.len()); debug!("check_files - Found {} files to check.", self.files_to_check.len());
true true
} }
@ -451,16 +451,18 @@ fn check_extension_availability(
debug_assert!(false, "Extension not really fully str"); debug_assert!(false, "Extension not really fully str");
return TypeOfFile::Unknown; return TypeOfFile::Unknown;
}; };
let extension_lowercase = extension_str.to_ascii_lowercase();
if images_extensions.contains(&extension_str) { if images_extensions.contains(&extension_lowercase.as_str()) {
TypeOfFile::Image TypeOfFile::Image
} else if zip_extensions.contains(&extension_str) { } else if zip_extensions.contains(&extension_lowercase.as_str()) {
TypeOfFile::ArchiveZip TypeOfFile::ArchiveZip
} else if audio_extensions.contains(&extension_str) { } else if audio_extensions.contains(&extension_lowercase.as_str()) {
TypeOfFile::Audio TypeOfFile::Audio
} else if pdf_extensions.contains(&extension_str) { } else if pdf_extensions.contains(&extension_lowercase.as_str()) {
TypeOfFile::PDF TypeOfFile::PDF
} else { } else {
eprintln!("File with unknown extension: {full_name:?} - {extension_lowercase}");
debug_assert!(false, "File with unknown extension"); debug_assert!(false, "File with unknown extension");
TypeOfFile::Unknown TypeOfFile::Unknown
} }

View file

@ -562,7 +562,8 @@ pub fn prepare_thread_handler_common(
let progress_thread_run = progress_thread_run.clone(); let progress_thread_run = progress_thread_run.clone();
let atomic_counter = atomic_counter.clone(); let atomic_counter = atomic_counter.clone();
thread::spawn(move || { thread::spawn(move || {
let mut time_since_last_send = SystemTime::now(); // Use earlier time, to send immediately first message
let mut time_since_last_send = SystemTime::now() - Duration::from_secs(10u64);
loop { loop {
if time_since_last_send.elapsed().unwrap().as_millis() > SEND_PROGRESS_DATA_TIME_BETWEEN as u128 { if time_since_last_send.elapsed().unwrap().as_millis() > SEND_PROGRESS_DATA_TIME_BETWEEN as u128 {

View file

@ -268,7 +268,7 @@ impl DuplicateFinder {
.group_by(group_by_func) .group_by(group_by_func)
.stop_receiver(stop_receiver) .stop_receiver(stop_receiver)
.progress_sender(progress_sender) .progress_sender(progress_sender)
.checking_method(CheckingMethod::Name) .checking_method(CheckingMethod::SizeName)
.build() .build()
.run(); .run();

View file

@ -193,6 +193,7 @@ impl SameMusic {
.stop_receiver(stop_receiver) .stop_receiver(stop_receiver)
.progress_sender(progress_sender) .progress_sender(progress_sender)
.common_data(&self.common_data) .common_data(&self.common_data)
.checking_method(self.check_type)
.max_stage(max_stage) .max_stage(max_stage)
.build() .build()
.run(); .run();

View file

@ -19,6 +19,58 @@ use crate::localizer_core::generate_translation_hashmap;
use crate::taskbar_progress::tbp_flags::TBPF_INDETERMINATE; use crate::taskbar_progress::tbp_flags::TBPF_INDETERMINATE;
use crate::taskbar_progress::TaskbarProgress; use crate::taskbar_progress::TaskbarProgress;
// Empty files
// 0 - Collecting files
// Empty folders
// 0 - Collecting folders
// Big files
// 0 - Collecting files
// Same music
// 0 - Collecting files
// 1 - Loading cache
// 2 - Checking tags / content
// 3 - Saving cache
// 4 - Checking tags / content - progress
// 5 - Only content - ending
// Similar images
// 0 - Collecting files
// 1 - Scanning images
// 2 - Comparing hashes
// Similar videos
// 0 - Collecting files
// 1 - Scanning videos
// Temporary files
// 0 - Collecting files
// Invalid symlinks
// 0 - Collecting files
// Broken files
// 0 - Collecting files
// 1 - Scanning files
// Bad extensions
// 0 - Collecting files
// 1 - Scanning files
// Duplicates - Hash
// 0 - Collecting files
// 1 - Loading cache
// 2 - Hash - first 1KB file
// 3 - Saving cache
// 4 - Loading cache
// 5 - Hash - normal hash
// 6 - Saving cache
// Duplicates - Name or SizeName or Size
// 0 - Collecting files
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn connect_progress_window(gui_data: &GuiData, progress_receiver: Receiver<ProgressData>) { pub fn connect_progress_window(gui_data: &GuiData, progress_receiver: Receiver<ProgressData>) {
let main_context = MainContext::default(); let main_context = MainContext::default();
@ -31,19 +83,12 @@ pub fn connect_progress_window(gui_data: &GuiData, progress_receiver: Receiver<P
loop { loop {
let item = progress_receiver.try_recv(); let item = progress_receiver.try_recv();
if let Ok(item) = item { if let Ok(item) = item {
match item.tool_type { if item.current_stage == 0 {
ToolType::Duplicate => process_bar_duplicates(&gui_data, &item), progress_collect_items(&gui_data, &item, item.tool_type != ToolType::EmptyFolders);
ToolType::EmptyFiles => process_bar_empty_files(&gui_data, &item), } else if check_if_loading_saving_cache(&item) {
ToolType::EmptyFolders => process_bar_empty_folder(&gui_data, &item), progress_save_load_cache(&gui_data, &item);
ToolType::BigFile => process_bar_big_files(&gui_data, &item), } else {
ToolType::SameMusic => process_bar_same_music(&gui_data, &item), progress_default(&gui_data, &item);
ToolType::SimilarImages => process_bar_similar_images(&gui_data, &item),
ToolType::SimilarVideos => process_bar_similar_videos(&gui_data, &item),
ToolType::TemporaryFiles => process_bar_temporary(&gui_data, &item),
ToolType::InvalidSymlinks => process_bar_invalid_symlinks(&gui_data, &item),
ToolType::BrokenFiles => process_bar_broken_files(&gui_data, &item),
ToolType::BadExtensions => process_bar_bad_extensions(&gui_data, &item),
ToolType::None => panic!(),
} }
} else { } else {
break; break;
@ -55,278 +100,123 @@ pub fn connect_progress_window(gui_data: &GuiData, progress_receiver: Receiver<P
main_context.spawn_local(future); main_context.spawn_local(future);
} }
pub fn check_if_loading_saving_cache(progress_data: &ProgressData) -> bool {
fn process_bar_empty_files(gui_data: &GuiData, item: &ProgressData) { matches!(
(progress_data.tool_type, progress_data.current_stage),
(ToolType::SameMusic, 1 | 3) | (ToolType::Duplicate, 1 | 3 | 4 | 6)
)
}
fn progress_save_load_cache(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone(); let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let taskbar_state = gui_data.taskbar_state.clone(); let taskbar_state = gui_data.taskbar_state.clone();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item))); progress_bar_current_stage.hide();
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE); taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
} let text = match (item.tool_type, item.checking_method, item.current_stage) {
(ToolType::SameMusic, CheckingMethod::AudioTags | CheckingMethod::AudioContent, 1) => {
fn process_bar_empty_folder(gui_data: &GuiData, item: &ProgressData) { flg!("progress_cache_loading")
let label_stage = gui_data.progress_window.label_stage.clone();
let taskbar_state = gui_data.taskbar_state.clone();
label_stage.set_text(&flg!(
"progress_scanning_empty_folders",
generate_translation_hashmap(vec![("folder_number", item.entries_checked.to_string())])
));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
fn process_bar_big_files(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let taskbar_state = gui_data.taskbar_state.clone();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
fn process_bar_same_music(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
} }
// Loading cache (ToolType::SameMusic, CheckingMethod::AudioTags | CheckingMethod::AudioContent, 3) => {
1 => { flg!("progress_cache_saving")
progress_bar_current_stage.hide();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_cache_loading"));
} }
2 => { (ToolType::Duplicate, CheckingMethod::Hash, 1) => {
progress_bar_current_stage.show(); flg!("progress_prehash_cache_loading")
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
match item.checking_method {
CheckingMethod::AudioTags => label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(item))),
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_content", progress_ratio_tm(item))),
_ => panic!(),
}
} }
// Saving cache (ToolType::Duplicate, CheckingMethod::Hash, 3) => {
3 => { flg!("progress_prehash_cache_saving")
progress_bar_current_stage.hide();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_cache_saving"));
} }
4 => { (ToolType::Duplicate, CheckingMethod::Hash, 4) => {
progress_bar_current_stage.show(); flg!("progress_hash_cache_loading")
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
match item.checking_method {
CheckingMethod::AudioTags => label_stage.set_text(&flg!("progress_scanning_music_tags_end", progress_ratio_tm(item))),
CheckingMethod::AudioContent => label_stage.set_text(&flg!("progress_scanning_music_content_end", progress_ratio_tm(item))),
_ => panic!(),
}
} }
5 => { (ToolType::Duplicate, CheckingMethod::Hash, 6) => {
progress_bar_current_stage.show(); flg!("progress_hash_cache_saving")
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
if item.checking_method == CheckingMethod::AudioContent {
label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(item)));
} else {
panic!();
}
}
_ => panic!(),
}
}
fn process_bar_similar_images(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_scanning_image", progress_ratio_tm(item)));
}
2 => {
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_comparing_image_hashes", progress_ratio_tm(item)));
}
_ => panic!(),
}
}
fn process_bar_similar_videos(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_scanning_video", progress_ratio_tm(item)));
}
_ => panic!(),
}
}
fn process_bar_temporary(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let taskbar_state = gui_data.taskbar_state.clone();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
fn process_bar_invalid_symlinks(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let taskbar_state = gui_data.taskbar_state.clone();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
fn process_bar_broken_files(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_scanning_broken_files", progress_ratio_tm(item)));
}
_ => panic!(),
}
}
fn process_bar_bad_extensions(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
match item.current_stage {
0 => {
progress_bar_current_stage.hide();
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
1 => {
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_scanning_extension_of_files", progress_ratio_tm(item)));
}
_ => panic!(),
}
}
fn process_bar_duplicates(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let grid_progress_stages = gui_data.progress_window.grid_progress_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
match item.checking_method {
CheckingMethod::Hash => {
label_stage.show();
match item.current_stage {
// Checking Size
0 => {
progress_bar_current_stage.hide();
progress_bar_all_stages.set_fraction(0f64);
label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
// Loading cache
1 | 4 => {
progress_bar_current_stage.hide();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
if item.current_stage == 1 {
label_stage.set_text(&flg!("progress_prehash_cache_loading"));
} else {
label_stage.set_text(&flg!("progress_hash_cache_loading"));
}
}
// Saving cache
3 | 6 => {
progress_bar_current_stage.hide();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
if item.current_stage == 3 {
label_stage.set_text(&flg!("progress_prehash_cache_saving"));
} else {
label_stage.set_text(&flg!("progress_hash_cache_saving"));
}
}
// Hash - first 1KB file
2 => {
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_analyzed_partial_hash", progress_ratio_tm(item)));
}
// Hash - normal hash
5 => {
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
label_stage.set_text(&flg!("progress_analyzed_full_hash", progress_ratio_tm(item)));
}
_ => {
panic!("Not available current_stage");
}
}
}
CheckingMethod::Name => {
label_stage.show();
grid_progress_stages.hide();
label_stage.set_text(&flg!("progress_scanning_name", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
CheckingMethod::SizeName => {
label_stage.show();
grid_progress_stages.hide();
label_stage.set_text(&flg!("progress_scanning_size_name", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
}
CheckingMethod::Size => {
label_stage.show();
grid_progress_stages.hide();
label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(item)));
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
} }
_ => panic!(), _ => panic!(),
}; };
label_stage.set_text(&text);
}
fn progress_collect_items(gui_data: &GuiData, item: &ProgressData, files: bool) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let taskbar_state = gui_data.taskbar_state.clone();
progress_bar_current_stage.hide();
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
match (item.tool_type, item.checking_method) {
(ToolType::Duplicate, CheckingMethod::Name) => {
label_stage.set_text(&flg!("progress_scanning_name", file_number_tm(item)));
return;
}
(ToolType::Duplicate, CheckingMethod::SizeName) => {
label_stage.set_text(&flg!("progress_scanning_size_name", file_number_tm(item)));
return;
}
(ToolType::Duplicate, CheckingMethod::Size | CheckingMethod::Hash) => {
label_stage.set_text(&flg!("progress_scanning_size", file_number_tm(item)));
return;
}
_ => {}
}
if files {
label_stage.set_text(&flg!("progress_scanning_general_file", file_number_tm(item)));
} else {
label_stage.set_text(&flg!(
"progress_scanning_empty_folders",
generate_translation_hashmap(vec![("folder_number", item.entries_checked.to_string())])
));
}
}
fn progress_default(gui_data: &GuiData, item: &ProgressData) {
let label_stage = gui_data.progress_window.label_stage.clone();
let progress_bar_current_stage = gui_data.progress_window.progress_bar_current_stage.clone();
let progress_bar_all_stages = gui_data.progress_window.progress_bar_all_stages.clone();
let taskbar_state = gui_data.taskbar_state.clone();
progress_bar_current_stage.show();
common_set_data(item, &progress_bar_all_stages, &progress_bar_current_stage, &taskbar_state);
taskbar_state.borrow().set_progress_state(TBPF_INDETERMINATE);
match (item.tool_type, item.checking_method, item.current_stage) {
(ToolType::SameMusic, CheckingMethod::AudioTags, 2) | (ToolType::SameMusic, CheckingMethod::AudioContent, 5) => {
label_stage.set_text(&flg!("progress_scanning_music_tags", progress_ratio_tm(item)));
}
(ToolType::SameMusic, CheckingMethod::AudioContent, 2) => {
label_stage.set_text(&flg!("progress_scanning_music_content", progress_ratio_tm(item)));
}
(ToolType::SameMusic, CheckingMethod::AudioTags, 4) => {
label_stage.set_text(&flg!("progress_scanning_music_tags_end", progress_ratio_tm(item)));
}
(ToolType::SameMusic, CheckingMethod::AudioContent, 4) => {
label_stage.set_text(&flg!("progress_scanning_music_content_end", progress_ratio_tm(item)));
}
(ToolType::SimilarImages, _, 1) => {
label_stage.set_text(&flg!("progress_scanning_image", progress_ratio_tm(item)));
}
(ToolType::SimilarImages, _, 2) => {
label_stage.set_text(&flg!("progress_comparing_image_hashes", progress_ratio_tm(item)));
}
(ToolType::SimilarVideos, _, 1) => {
label_stage.set_text(&flg!("progress_scanning_video", progress_ratio_tm(item)));
}
(ToolType::BrokenFiles, _, 1) => {
label_stage.set_text(&flg!("progress_scanning_broken_files", progress_ratio_tm(item)));
}
(ToolType::BadExtensions, _, 1) => {
label_stage.set_text(&flg!("progress_scanning_extension_of_files", progress_ratio_tm(item)));
}
(ToolType::Duplicate, CheckingMethod::Hash, 2) => {
label_stage.set_text(&flg!("progress_analyzed_partial_hash", progress_ratio_tm(item)));
}
(ToolType::Duplicate, CheckingMethod::Hash, 5) => {
label_stage.set_text(&flg!("progress_analyzed_full_hash", progress_ratio_tm(item)));
}
_ => unreachable!(),
}
} }
fn common_set_data(item: &ProgressData, progress_bar_all_stages: &ProgressBar, progress_bar_current_stage: &ProgressBar, taskbar_state: &Rc<RefCell<TaskbarProgress>>) { fn common_set_data(item: &ProgressData, progress_bar_all_stages: &ProgressBar, progress_bar_current_stage: &ProgressBar, taskbar_state: &Rc<RefCell<TaskbarProgress>>) {