diff --git a/.github/workflows/linux_cli.yml b/.github/workflows/linux_cli.yml index 0509201a..689a4154 100644 --- a/.github/workflows/linux_cli.yml +++ b/.github/workflows/linux_cli.yml @@ -32,6 +32,9 @@ jobs: name: czkawka_cli-${{ runner.os }} path: target/release/czkawka_cli + - name: Build test version + run: cargo build --profile test --bin czkawka_cli + - name: Linux Regression Test run: | wget https://github.com/qarmin/czkawka/releases/download/6.0.0/TestFiles.zip diff --git a/Cargo.toml b/Cargo.toml index 0184c4ab..b1a74c97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,4 +28,9 @@ overflow-checks = true # Optimize all dependencies except application/workspaces, even in debug builds [profile.dev.package."*"] -opt-level = 3 \ No newline at end of file +opt-level = 3 + +[profile.test] +debug-assertions = true # Forces to crash when there is duplicated item in cli +overflow-checks = true +opt-level = 3 diff --git a/ci_tester/Cargo.toml b/ci_tester/Cargo.toml index 38f354a3..39f00c9d 100644 --- a/ci_tester/Cargo.toml +++ b/ci_tester/Cargo.toml @@ -5,6 +5,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +debug-assertions = true +overflow-checks = true + [dependencies] state = "0.6.0" handsome_logger = "0.8.0" diff --git a/ci_tester/src/main.rs b/ci_tester/src/main.rs index 04e47311..14850b3e 100644 --- a/ci_tester/src/main.rs +++ b/ci_tester/src/main.rs @@ -17,12 +17,24 @@ static COLLECTED_FILES: state::InitCell = state::InitCell::new() const ATTEMPTS: u32 = 10; const PRINT_MESSAGES_CZKAWKA: bool = true; +fn test_args() { + let modes = ["dup", "big", "empty-folders", "empty-files", "temp", "image", "symlinks", "broken", "ext", "video", "music"]; + for mode in modes { + let _ = fs::remove_dir_all("RandomDirWithoutContent"); + fs::create_dir_all("RandomDirWithoutContent").expect("Should not fail in tests"); + run_with_good_status(&[CZKAWKA_PATH.get().as_str(), mode, "-d", "RandomDirWithoutContent"], false); + } +} + // App runs - ./ci_tester PATH_TO_CZKAWKA fn main() { handsome_logger::init().expect("Should not fail in tests"); let args: Vec = std::env::args().collect(); let path_to_czkawka = args[1].clone(); CZKAWKA_PATH.set(path_to_czkawka); + + test_args(); + remove_test_dir(); run_with_good_status(&["ls"], false); unzip_files(); diff --git a/czkawka_cli/src/commands.rs b/czkawka_cli/src/commands.rs index 9d2fb8d9..86d1a0a6 100644 --- a/czkawka_cli/src/commands.rs +++ b/czkawka_cli/src/commands.rs @@ -88,6 +88,8 @@ pub enum Commands { pub struct DuplicatesArgs { #[clap(flatten)] pub common_cli_items: CommonCliItems, + #[clap(flatten)] + pub referenced_folder: ReferencedFolder, #[clap( short = 'p', long, @@ -198,6 +200,8 @@ pub struct TemporaryArgs { pub struct SimilarImagesArgs { #[clap(flatten)] pub common_cli_items: CommonCliItems, + #[clap(flatten)] + pub referenced_folder: ReferencedFolder, #[clap( short, long, @@ -264,6 +268,8 @@ pub struct SameMusicArgs { #[clap(flatten)] pub common_cli_items: CommonCliItems, #[clap(flatten)] + pub referenced_folder: ReferencedFolder, + #[clap(flatten)] pub delete_method: DMethod, #[clap(flatten)] pub dry_run: DryRun, @@ -386,6 +392,8 @@ pub struct SimilarVideosArgs { #[clap(flatten)] pub common_cli_items: CommonCliItems, #[clap(flatten)] + pub referenced_folder: ReferencedFolder, + #[clap(flatten)] pub delete_method: DMethod, #[clap(flatten)] pub allow_hard_links: AllowHardLinks, @@ -437,7 +445,7 @@ pub struct CommonCliItems { long, required = true, help = "Directorie(s) to search", - long_help = "List of directorie(s) which will be searched(absolute path)" + long_help = "List of directorie(s) which will be searched(absolute path) - this directories are not set as reference folders" )] pub directories: Vec, #[clap( @@ -495,6 +503,17 @@ pub struct FileToSave { pub file_to_save: Option, } +#[derive(Debug, clap::Args)] +pub struct ReferencedFolder { + #[clap( + short, + long, + help = "Reference directorie(s) to search", + long_help = "List of directorie(s) which will be searched(absolute path) - this directories are set as reference folders, so will not be visible in the results" + )] + pub reference_folders: Vec, +} + #[derive(Debug, clap::Args)] pub struct JsonCompactFileToSave { #[clap(short = 'C', long, value_name = "json-file-name", help = "Saves the results into the compact json file")] diff --git a/czkawka_cli/src/main.rs b/czkawka_cli/src/main.rs index 8a580ef6..f48016d1 100644 --- a/czkawka_cli/src/main.rs +++ b/czkawka_cli/src/main.rs @@ -1,6 +1,7 @@ #![allow(clippy::needless_late_init)] #![warn(clippy::unwrap_used)] +use std::path::PathBuf; use std::thread; use clap::Parser; @@ -79,6 +80,7 @@ fn main() { fn duplicates(duplicates: DuplicatesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender) { let DuplicatesArgs { common_cli_items, + referenced_folder, minimal_file_size, maximal_file_size, minimal_cached_file_size, @@ -103,7 +105,7 @@ fn duplicates(duplicates: DuplicatesArgs, stop_receiver: &Receiver<()>, progress ); let mut item = DuplicateFinder::new(params); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, Some(referenced_folder.reference_folders.as_ref())); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); item.set_delete_method(delete_method.delete_method); @@ -119,7 +121,7 @@ fn empty_folders(empty_folders: EmptyFoldersArgs, stop_receiver: &Receiver<()>, let mut item = EmptyFolder::new(); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, None); if delete_folders { item.set_delete_method(DeleteMethod::Delete); } @@ -141,7 +143,7 @@ fn biggest_files(biggest_files: BiggestFilesArgs, stop_receiver: &Receiver<()>, let params = BigFileParameters::new(number_of_files, big_files_mode); let mut item = BigFile::new(params); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, None); if delete_files { item.set_delete_method(DeleteMethod::Delete); } @@ -156,7 +158,7 @@ fn empty_files(empty_files: EmptyFilesArgs, stop_receiver: &Receiver<()>, progre let mut item = EmptyFiles::new(); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, None); if delete_files { item.set_delete_method(DeleteMethod::Delete); } @@ -171,7 +173,7 @@ fn temporary(temporary: TemporaryArgs, stop_receiver: &Receiver<()>, progress_se let mut item = Temporary::new(); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, None); if delete_files { item.set_delete_method(DeleteMethod::Delete); } @@ -184,6 +186,7 @@ fn temporary(temporary: TemporaryArgs, stop_receiver: &Receiver<()>, progress_se fn similar_images(similar_images: SimilarImagesArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender) { let SimilarImagesArgs { common_cli_items, + referenced_folder, minimal_file_size, maximal_file_size, similarity_preset, @@ -207,7 +210,7 @@ fn similar_images(similar_images: SimilarImagesArgs, stop_receiver: &Receiver<() ); let mut item = SimilarImages::new(params); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, Some(referenced_folder.reference_folders.as_ref())); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); item.set_delete_method(delete_method.delete_method); @@ -221,6 +224,7 @@ fn similar_images(similar_images: SimilarImagesArgs, stop_receiver: &Receiver<() fn same_music(same_music: SameMusicArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender) { let SameMusicArgs { common_cli_items, + referenced_folder, delete_method, minimal_file_size, maximal_file_size, @@ -243,7 +247,7 @@ fn same_music(same_music: SameMusicArgs, stop_receiver: &Receiver<()>, progress_ ); let mut item = SameMusic::new(params); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, Some(referenced_folder.reference_folders.as_ref())); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); item.set_delete_method(delete_method.delete_method); @@ -259,7 +263,7 @@ fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs, stop_receiver: &Recei let mut item = InvalidSymlinks::new(); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, None); if delete_files { item.set_delete_method(DeleteMethod::Delete); } @@ -283,7 +287,7 @@ fn broken_files(broken_files: BrokenFilesArgs, stop_receiver: &Receiver<()>, pro let params = BrokenFilesParameters::new(checked_type); let mut item = BrokenFiles::new(params); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, None); if delete_files { item.set_delete_method(DeleteMethod::Delete); } @@ -295,6 +299,7 @@ fn broken_files(broken_files: BrokenFilesArgs, stop_receiver: &Receiver<()>, pro fn similar_videos(similar_videos: SimilarVideosArgs, stop_receiver: &Receiver<()>, progress_sender: &Sender) { let SimilarVideosArgs { + referenced_folder, common_cli_items, tolerance, minimal_file_size, @@ -308,7 +313,7 @@ fn similar_videos(similar_videos: SimilarVideosArgs, stop_receiver: &Receiver<() let params = SimilarVideosParameters::new(tolerance, ignore_same_size.ignore_same_size, !allow_hard_links.allow_hard_links); let mut item = SimilarVideos::new(params); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, Some(referenced_folder.reference_folders.as_ref())); item.set_minimal_file_size(minimal_file_size); item.set_maximal_file_size(maximal_file_size); item.set_delete_method(delete_method.delete_method); @@ -325,7 +330,7 @@ fn bad_extensions(bad_extensions: BadExtensionsArgs, stop_receiver: &Receiver<() let params = BadExtensionsParameters::new(); let mut item = BadExtensions::new(params); - set_common_settings(&mut item, &common_cli_items); + set_common_settings(&mut item, &common_cli_items, None); item.find_bad_extensions_files(Some(stop_receiver), Some(progress_sender)); @@ -354,12 +359,18 @@ fn save_and_print_results(component: &mut T, commo component.get_text_messages().print_messages(); } -fn set_common_settings(component: &mut T, common_cli_items: &CommonCliItems) +fn set_common_settings(component: &mut T, common_cli_items: &CommonCliItems, referenced_folders: Option<&Vec>) where T: CommonData + PrintResults, { set_number_of_threads(common_cli_items.thread_number); + let mut included_directories = common_cli_items.directories.clone(); + if let Some(referenced_folders) = referenced_folders { + included_directories.extend_from_slice(referenced_folders); + component.set_reference_directory(referenced_folders.clone()); + } + 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()); diff --git a/czkawka_core/src/common_directory.rs b/czkawka_core/src/common_directory.rs index cf2524ca..22f96325 100644 --- a/czkawka_core/src/common_directory.rs +++ b/czkawka_core/src/common_directory.rs @@ -119,7 +119,7 @@ impl Directories { // Try to canonicalize them if cfg!(windows) { // Only canonicalize if it's not a network path - // This can be check by checking if path starts with \\?\UNC\ + // This can be done by checking if path starts with \\?\UNC\ if let Ok(dir_can) = directory.canonicalize() { let dir_can_str = dir_can.to_string_lossy().to_string(); if let Some(dir_can_str) = dir_can_str.strip_prefix(r"\\?\") { diff --git a/czkawka_core/src/same_music.rs b/czkawka_core/src/same_music.rs index ab5f2480..96defdfe 100644 --- a/czkawka_core/src/same_music.rs +++ b/czkawka_core/src/same_music.rs @@ -398,7 +398,7 @@ impl SameMusic { } }) .while_some() - .filter_map(|e| e) + .flatten() .collect::>(); debug!("read_tags - ended reading tags"); diff --git a/justfile b/justfile index d82ab850..e312fb09 100644 --- a/justfile +++ b/justfile @@ -18,10 +18,10 @@ krokiet_r: krokiet_dark: RUST_BACKTRACE=1 SLINT_STYLE=fluent-dark cargo run --bin krokiet -cli: - RUST_BACKTRACE=1 cargo run --bin czkawka_cli -cli_r: - RUST_BACKTRACE=1 cargo run --bin czkawka_cli --release +cli +args: + RUST_BACKTRACE=1 cargo run --bin czkawka_cli -- {{args}} +cli_r args: + RUST_BACKTRACE=1 cargo run --bin czkawka_cli --release -- {{args}} cli_help: cargo run --bin czkawka_cli -- --help