diff --git a/.rustfmt.toml b/.rustfmt.toml index 68405c5..2098d46 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,4 +1,4 @@ newline_style = "Unix" -max_width = 200 +max_width = 250 remove_nested_parens = true diff --git a/README.md b/README.md index 457f83a..0c0cdec 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,13 @@ This is my first ever project in Rust so probably a lot of things are written in ## Done - Rich instruction with examples - CLI(`cargo run --bin czkawka_cli`) -- Duplicated file finding - CLI +- GTK Frontend(Still WIP) - (`cargo run --bin czkawka_gui`) +- Orbtk Frontend(Still very early WIP) - (`cargo run --bin czkawka_gui_orbtk`) +- Duplicated file finding - Including and excluding directories(absolute paths) - Option to remove all except newest, oldest and one oldest or newest - Fast(by size) or accurate(by hash) file checking -- Empty folders finding - CLI +- Empty folders finding - Advanced empty files finding(finds and remove folders which contains only empty folders) - Option to remove all files @@ -21,8 +23,6 @@ This is my first ever project in Rust so probably a lot of things are written in - Duplicated file finding - CLI - saving results to file - support for * when excluding files and folders -- GUI with GTK -- Alternative GUI with Orbtk - Finding files with debug symbols - Support for showing only duplicates with specific extension, name(Regex support needed) - Maybe windows support, but this will need some refactoring in code diff --git a/czkawka_cli/src/main.rs b/czkawka_cli/src/main.rs index 14a39a8..0c65dba 100644 --- a/czkawka_cli/src/main.rs +++ b/czkawka_cli/src/main.rs @@ -6,7 +6,7 @@ fn main() { let mut all_arguments: Vec = env::args().collect(); let mut commands_arguments: Vec = Vec::new(); - println!("{:?}", all_arguments); + // println!("{:?}", all_arguments); all_arguments.remove(0); // Removing program name from arguments @@ -23,10 +23,7 @@ fn main() { if argument.starts_with("--") { commands_arguments.push(argument); } else if argument.starts_with('-') { - let a: ArgumentsPair = ArgumentsPair { - command: argument, - argument: Option::None, - }; + let a: ArgumentsPair = ArgumentsPair { command: argument, argument: Option::None }; arguments.push(a); } else { if arguments.is_empty() { @@ -42,16 +39,16 @@ fn main() { } } - for a in &arguments { - println!( - "Argument number {} - {}", - a.command, - match &a.argument { - Some(t) => t.clone(), - None => "MISSING_ARGUMENT".to_string(), - } - ); - } + // for a in &arguments { + // println!( + // "Argument number {} - {}", + // a.command, + // match &a.argument { + // Some(t) => t.clone(), + // None => "MISSING_ARGUMENT".to_string(), + // } + // ); + // } if commands_arguments.is_empty() { println! {"FATAL ERROR: Missing type of app which you want to run, please read help for more info."}; @@ -63,7 +60,9 @@ fn main() { let mut check_method: duplicate::CheckingMethod = duplicate::CheckingMethod::HASH; if ArgumentsPair::has_command(&arguments, "-i") { - df.set_include_directory(ArgumentsPair::get_argument(&arguments, "-i", false)); + if !df.set_include_directory(ArgumentsPair::get_argument(&arguments, "-i", false)) { + process::exit(1); + } } else { println!("FATAL ERROR: Parameter -i with set of included files is required."); process::exit(1); @@ -74,12 +73,16 @@ fn main() { if ArgumentsPair::has_command(&arguments, "-s") { let min_size = match ArgumentsPair::get_argument(&arguments, "-s", false).parse::() { - Ok(t) => t, + Ok(t) => { + if t == 0 { + println!("ERROR: Minimum file size must be at least 1 byte."); + 1 + } else { + t + } + } Err(_) => { - println!( - "FATAL ERROR: \"{}\" is not valid file size(allowed range <0,u64::max>)", - ArgumentsPair::get_argument(&arguments, "-s", false) - ); + println!("FATAL ERROR: \"{}\" is not valid file size(allowed range <1,u64::max>)", ArgumentsPair::get_argument(&arguments, "-s", false)); process::exit(1); } }; @@ -128,6 +131,38 @@ fn main() { } df.find_duplicates(&check_method, &delete_method); + + let info = df.get_infos(); + + if !info.messages.is_empty() { + println!("-------------------------------MESSAGES--------------------------------"); + } + for i in &info.messages { + println!("{}", i); + } + if !info.messages.is_empty() { + println!("---------------------------END OF MESSAGES-----------------------------"); + } + + if !info.warnings.is_empty() { + println!("-------------------------------WARNINGS--------------------------------"); + } + for i in &info.warnings { + println!("{}", i); + } + if !info.warnings.is_empty() { + println!("---------------------------END OF WARNINGS-----------------------------"); + } + + if !info.errors.is_empty() { + println!("--------------------------------ERRORS---------------------------------"); + } + for i in &info.errors { + println!("{}", i); + } + if !info.errors.is_empty() { + println!("----------------------------END OF ERRORS------------------------------"); + } } "--h" | "--help" => { print_help(); @@ -218,6 +253,6 @@ impl ArgumentsPair { }; } } - panic!("FATAL ERROR: Get argument should always return value"); + panic!("INTERNAL ERROR: Get argument should always return value"); } } diff --git a/czkawka_core/src/common.rs b/czkawka_core/src/common.rs index 450daae..cd48e2a 100644 --- a/czkawka_core/src/common.rs +++ b/czkawka_core/src/common.rs @@ -8,10 +8,6 @@ impl Common { if true { return; } - println!( - "Execution of function \"{}\" took {:?}", - function_name, - end_time.duration_since(start_time).expect("Time cannot go reverse.") - ); + println!("Execution of function \"{}\" took {:?}", function_name, end_time.duration_since(start_time).expect("Time cannot go reverse.")); } } diff --git a/czkawka_core/src/duplicate.rs b/czkawka_core/src/duplicate.rs index f475404..1f99a3d 100644 --- a/czkawka_core/src/duplicate.rs +++ b/czkawka_core/src/duplicate.rs @@ -1,11 +1,11 @@ // TODO when using GUI all or most println!() should be used as variables passed by argument use humansize::{file_size_opts as options, FileSize}; use std::collections::{BTreeMap, HashMap}; +use std::fs; use std::fs::{File, Metadata}; use std::io::prelude::*; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; -use std::{fs, process}; use crate::common::Common; @@ -32,6 +32,7 @@ struct FileEntry { pub modified_date: SystemTime, } +/// Struct with required information's to work pub struct DuplicateFinder { infos: Info, files_with_identical_size: HashMap>, @@ -43,23 +44,36 @@ pub struct DuplicateFinder { min_file_size: u64, } +/// Info struck with helpful information's about results pub struct Info { - number_of_checked_files: usize, - number_of_ignored_files: usize, - number_of_checked_folders: usize, - number_of_ignored_things: usize, - number_of_duplicated_files: usize, - lost_space: u64, + pub errors: Vec, + pub warnings: Vec, + pub messages: Vec, + pub number_of_checked_files: usize, + pub number_of_checked_folders: usize, + pub number_of_ignored_files: usize, + pub number_of_ignored_things: usize, + pub number_of_duplicated_files: usize, + pub lost_space: u64, + pub number_of_removed_files: usize, + pub number_of_failed_to_remove_files: usize, + pub gained_space: u64, } impl Info { pub fn new() -> Info { Info { + errors: vec![], + warnings: vec![], + messages: vec![], number_of_checked_files: 0, number_of_ignored_files: 0, number_of_checked_folders: 0, number_of_ignored_things: 0, number_of_duplicated_files: 0, lost_space: 0, + number_of_removed_files: 0, + number_of_failed_to_remove_files: 0, + gained_space: 0, } } } @@ -83,17 +97,20 @@ impl DuplicateFinder { allowed_extensions: vec![], } } + pub fn get_infos(&self) -> &Info { + &self.infos + } - pub fn find_duplicates(mut self, check_method: &CheckingMethod, delete_method: &DeleteMethod) { + pub fn find_duplicates(&mut self, check_method: &CheckingMethod, delete_method: &DeleteMethod) { self.optimize_directories(); self.check_files_size(); self.remove_files_with_unique_size(); if *check_method == CheckingMethod::HASH { self.check_files_hash(); } - self.debug_print(); self.calculate_lost_space(check_method); self.delete_files(check_method, delete_method); + self.debug_print(); } pub fn set_min_file_size(&mut self, min_size: u64) { @@ -106,7 +123,8 @@ impl DuplicateFinder { } pub fn set_allowed_extensions(&mut self, mut allowed_extensions: String) { if allowed_extensions.is_empty() { - println!("No allowed extension was provided, so all are allowed"); + self.infos.messages.push("No allowed extension was provided, so all are allowed".to_string()); + return; } allowed_extensions = allowed_extensions.replace("IMAGE", "jpg,kra,gif,png,bmp,tiff,webp,hdr,svg"); allowed_extensions = allowed_extensions.replace("VIDEO", "mp4,flv,mkv,webm,vob,ogv,gifv,avi,mov,wmv,mpg,m4v,m4p,mpeg,3gp"); @@ -121,7 +139,7 @@ impl DuplicateFinder { if extension.contains('.') { if !extension.starts_with('.') { - println!("{} is not valid extension(valid extension doesn't have dot inside)", extension); + self.infos.warnings.push(extension + " is not valid extension(valid extension doesn't have dot inside)"); continue; } extension = extension.replace('.', ""); @@ -132,14 +150,15 @@ impl DuplicateFinder { } if self.allowed_extensions.is_empty() { - println!("No valid extensions were provided, so allowing all extensions by default."); + self.infos.messages.push("No valid extensions were provided, so allowing all extensions by default.".to_string()); } } - pub fn set_include_directory(&mut self, mut include_directory: String) { + pub fn set_include_directory(&mut self, mut include_directory: String) -> bool { // let start_time: SystemTime = SystemTime::now(); if include_directory.is_empty() { - println!("At least one directory must be provided"); + self.infos.errors.push("At least one directory must be provided".to_string()); + return false; } include_directory = include_directory.replace("\"", ""); @@ -152,27 +171,20 @@ impl DuplicateFinder { if directory == "" { continue; } - if directory == "/" { - println!("Using / is probably not good idea, you may go out of ram."); - } if directory.contains('*') { - println!("Include Directory ERROR: Wildcards are not supported, ignoring path {}.", directory); - continue; - } - if directory.starts_with('~') { - println!("Include Directory ERROR: ~ in path isn't supported, ignoring path {}.", directory); + self.infos.warnings.push("Include Directory Warning: Wildcards in path are not supported, ignoring ".to_string() + &*directory); continue; } if !directory.starts_with('/') { - println!("Include Directory ERROR: Relative path are not supported, ignoring path {}.", directory); + self.infos.warnings.push("Include Directory Warning: Relative path are not supported, ignoring ".to_string() + &*directory); continue; } if !Path::new(&directory).exists() { - println!("Include Directory ERROR: Path {} doesn't exists.", directory); + self.infos.warnings.push("Include Directory Warning: Provided folder path must exits, ignoring ".to_string() + &*directory); continue; } if !Path::new(&directory).is_dir() { - println!("Include Directory ERROR: {} isn't folder.", directory); + self.infos.warnings.push("Include Directory Warning: Provided path must point at the directory, ignoring ".to_string() + &*directory); continue; } @@ -185,13 +197,14 @@ impl DuplicateFinder { } if checked_directories.is_empty() { - println!("Not found even one correct path to include."); - process::exit(1); + self.infos.errors.push("Include Directory ERROR: Not found even one correct path to include which is required.".to_string()); + return false; } self.included_directories = checked_directories; //Common::print_time(start_time, SystemTime::now(), "set_include_directory".to_string()); + true } pub fn set_exclude_directory(&mut self, mut exclude_directory: String) { @@ -211,27 +224,23 @@ impl DuplicateFinder { continue; } if directory == "/" { - println!("Exclude Directory ERROR: Excluding / is pointless, because it means that no files will be scanned."); + self.infos.errors.push("Exclude Directory ERROR: Excluding / is pointless, because it means that no files will be scanned.".to_string()); break; } if directory.contains('*') { - println!("Exclude Directory ERROR: Wildcards are not supported, ignoring path {}.", directory); - continue; - } - if directory.starts_with('~') { - println!("Exclude Directory ERROR: ~ in path isn't supported, ignoring path {}.", directory); + self.infos.warnings.push("Exclude Directory Warning: Wildcards in path are not supported, ignoring ".to_string() + &*directory); continue; } if !directory.starts_with('/') { - println!("Exclude Directory ERROR: Relative path are not supported, ignoring path {}.", directory); + self.infos.warnings.push("Exclude Directory Warning: Relative path are not supported, ignoring ".to_string() + &*directory); continue; } if !Path::new(&directory).exists() { - println!("Exclude Directory ERROR: Path {} doesn't exists.", directory); + self.infos.warnings.push("Exclude Directory Warning: Provided folder path must exits, ignoring ".to_string() + &*directory); continue; } if !Path::new(&directory).is_dir() { - println!("Exclude Directory ERROR: {} isn't folder.", directory); + self.infos.warnings.push("Exclude Directory Warning: Provided path must point at the directory, ignoring ".to_string() + &*directory); continue; } @@ -266,23 +275,10 @@ impl DuplicateFinder { self.infos.lost_space = bytes; } - // TODO - Still isn't used but it will be probably required with GUI - // pub fn clear(&mut self) { - // - // self.number_of_checked_files = 0; - // self.number_of_checked_folders = 0; - // self.number_of_ignored_things = 0; - // self.number_of_files_which_has_duplicated_entries = 0; - // self.number_of_duplicated_files = 0; - // self.files_sizeclear(); - // self.excluded_directories.clear(); - // self.included_directories.clear(); - // } fn check_files_size(&mut self) { // TODO maybe add multithreading checking for file hash let start_time: SystemTime = SystemTime::now(); - let mut folders_to_check: Vec = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and - // big enough to store most of paths without needing to resize vector + let mut folders_to_check: Vec = Vec::with_capacity(1024 * 2); // This should be small enough too not see to big difference and big enough to store most of paths without needing to resize vector // Add root folders for finding for id in &self.included_directories { @@ -296,21 +292,31 @@ impl DuplicateFinder { let read_dir = match fs::read_dir(¤t_folder) { Ok(t) => t, - _ => continue, + Err(_) => { + self.infos.warnings.push("Cannot open dir ".to_string() + &*current_folder); + continue; + } // Permissions denied }; for entry in read_dir { let entry_data = match entry { Ok(t) => t, - Err(_) => continue, //Permissions denied + Err(_) => { + self.infos.warnings.push("Cannot read entry in dir ".to_string() + &*current_folder); + continue; + } //Permissions denied }; let metadata: Metadata = match entry_data.metadata() { Ok(t) => t, - Err(_) => continue, //Permissions denied + Err(_) => { + self.infos.warnings.push("Cannot read metadata in dir ".to_string() + &*current_folder); + continue; + } //Permissions denied }; if metadata.is_dir() { - if entry_data.file_name().into_string().is_err() { - continue; // Permissions denied - } + // if entry_data.file_name().into_string().is_err() { // Probably this can be removed, if crash still will be happens, then uncomment this line + // self.infos.warnings.push("Cannot read folder name in dir ".to_string() + &*current_folder); + // continue; // Permissions denied + // } let mut is_excluded_dir = false; next_folder = "".to_owned() + ¤t_folder + &entry_data.file_name().into_string().unwrap() + "/"; @@ -324,8 +330,6 @@ impl DuplicateFinder { folders_to_check.push(next_folder); } self.infos.number_of_checked_folders += 1; - - //println!("Directory\t - {:?}", next_folder); // DEBUG } else if metadata.is_file() { let mut have_valid_extension: bool; let file_name_lowercase: String = entry_data.file_name().into_string().unwrap().to_lowercase(); @@ -344,26 +348,27 @@ impl DuplicateFinder { if metadata.len() >= self.min_file_size && have_valid_extension { let current_file_name = "".to_owned() + ¤t_folder + &entry_data.file_name().into_string().unwrap(); - // println!("File\t\t - {:?}", current_file_name); // DEBUG - //file_to_check + let fe: FileEntry = FileEntry { - path: current_file_name, + path: current_file_name.clone(), size: metadata.len(), created_date: match metadata.created() { Ok(t) => t, - Err(_) => SystemTime::now(), + Err(_) => { + self.infos.warnings.push("Unable to get creation date from file ".to_string() + &*current_file_name); + SystemTime::now() + } // Permissions Denied }, modified_date: match metadata.modified() { Ok(t) => t, - Err(_) => SystemTime::now(), + Err(_) => { + self.infos.warnings.push("Unable to get modification date from file ".to_string() + &*current_file_name); + SystemTime::now() + } // Permissions Denied }, }; - // // self.files_with_identical_size.entry from below should be faster according to clippy - // if !self.files_with_identical_size.contains_key(&metadata.len()) { - // self.files_with_identical_size.insert(metadata.len(), Vec::new()); - // } - self.files_with_identical_size.entry(metadata.len()).or_insert_with(Vec::new); + self.files_with_identical_size.entry(metadata.len()).or_insert_with(Vec::new); self.files_with_identical_size.get_mut(&metadata.len()).unwrap().push(fe); self.infos.number_of_checked_files += 1; @@ -372,7 +377,6 @@ impl DuplicateFinder { } } else { // Probably this is symbolic links so we are free to ignore this - // println!("Found another type of file {} {:?}","".to_owned() + ¤t_folder + &entry_data.file_name().into_string().unwrap(), metadata) //DEBUG self.infos.number_of_ignored_things += 1; } } @@ -414,6 +418,7 @@ impl DuplicateFinder { file_handler = match File::open(&file_entry.1.path) { Ok(t) => t, Err(_) => { + self.infos.warnings.push("Unable to check hash of file ".to_string() + &*file_entry.1.path); continue; } }; @@ -426,6 +431,7 @@ impl DuplicateFinder { let n = match file_handler.read(&mut buffer) { Ok(t) => t, Err(_) => { + self.infos.warnings.push("Error happened when checking hash of file ".to_string() + &*file_entry.1.path); error_reading_file = true; break; } @@ -454,14 +460,11 @@ impl DuplicateFinder { #[allow(dead_code)] /// Setting include directories, panics when there is not directories available fn debug_print(&self) { - if true { - return; - } println!("---------------DEBUG PRINT---------------"); - println!("Number of all checked files - {}", self.infos.number_of_checked_files); - println!("Number of all ignored files - {}", self.infos.number_of_ignored_files); - println!("Number of all checked folders - {}", self.infos.number_of_checked_folders); - println!("Number of all ignored things - {}", self.infos.number_of_ignored_things); + println!("Number of checked files - {}", self.infos.number_of_checked_files); + println!("Number of checked folders - {}", self.infos.number_of_checked_folders); + println!("Number of ignored files - {}", self.infos.number_of_ignored_files); + println!("Number of ignored things(like symbolic links) - {}", self.infos.number_of_ignored_things); println!("Number of duplicated files - {}", self.infos.number_of_duplicated_files); let mut file_size: u64 = 0; for i in &self.files_with_identical_size { @@ -475,14 +478,17 @@ impl DuplicateFinder { } } println!("Hashed Files list size - {} ({})", self.files_with_identical_hashes.len(), hashed_file_size); + println!("Number of removed files - {}", self.infos.number_of_removed_files); + println!("Number of failed to remove files - {}", self.infos.number_of_failed_to_remove_files); + println!("Lost space - {} ({} bytes)", self.infos.lost_space.file_size(options::BINARY).unwrap(), self.infos.lost_space); + println!("Gained space by removing duplicated entries - {} ({} bytes)", self.infos.gained_space.file_size(options::BINARY).unwrap(), self.infos.gained_space); println!("Excluded directories - {:?}", self.excluded_directories); println!("Included directories - {:?}", self.included_directories); println!("-----------------------------------------"); } - #[allow(dead_code)] /// Print information about duplicated entries - fn print_duplicated_entries(&self, check_method: &CheckingMethod) { + pub fn print_duplicated_entries(&self, check_method: &CheckingMethod) { let start_time: SystemTime = SystemTime::now(); let mut number_of_files: u64 = 0; let mut number_of_groups: u64 = 0; @@ -538,7 +544,7 @@ impl DuplicateFinder { /// ``` // let df : DuplicateFinder = saf /// ``` - fn optimize_directories(&mut self) { + fn optimize_directories(&mut self) -> bool { let start_time: SystemTime = SystemTime::now(); let mut optimized_included: Vec = Vec::::new(); @@ -646,14 +652,15 @@ impl DuplicateFinder { // optimized_excluded = Vec::::new(); if self.included_directories.is_empty() { - println!("Optimize Directories ERROR: Excluded directories overlaps all included directories."); - process::exit(1); + self.infos.errors.push("Optimize Directories ERROR: Excluded directories overlaps all included directories.".to_string()); + return false; } // Not needed, but better is to have sorted everything self.excluded_directories.sort(); self.included_directories.sort(); Common::print_time(start_time, SystemTime::now(), "optimize_directories".to_string()); + true } fn delete_files(&mut self, check_method: &CheckingMethod, delete_method: &DeleteMethod) { @@ -661,28 +668,28 @@ impl DuplicateFinder { return; } let start_time: SystemTime = SystemTime::now(); - let mut errors: Vec = Vec::new(); + match check_method { CheckingMethod::HASH => { for entry in &self.files_with_identical_hashes { for vector in entry.1 { - delete_files(&vector, &delete_method, &mut errors); + let tuple: (u64, usize, usize) = delete_files(&vector, &delete_method, &mut self.infos.warnings); + self.infos.gained_space += tuple.0; + self.infos.number_of_removed_files += tuple.1; + self.infos.number_of_failed_to_remove_files += tuple.2; } } } CheckingMethod::SIZE => { for entry in &self.files_with_identical_size { - delete_files(&entry.1, &delete_method, &mut errors); + let tuple: (u64, usize, usize) = delete_files(&entry.1, &delete_method, &mut self.infos.warnings); + self.infos.gained_space += tuple.0; + self.infos.number_of_removed_files += tuple.1; + self.infos.number_of_failed_to_remove_files += tuple.2; } } } - if !errors.is_empty() { - println!("Failed to delete some files, because they have got deleted earlier or you have too low privileges - try run it as root."); - println!("List of files which wasn't deleted:"); - } - for i in errors { - println!("{}", i); - } + Common::print_time(start_time, SystemTime::now(), "delete_files".to_string()); } } @@ -692,10 +699,15 @@ impl Default for DuplicateFinder { } } -fn delete_files(vector: &[FileEntry], delete_method: &DeleteMethod, errors: &mut Vec) { +fn delete_files(vector: &[FileEntry], delete_method: &DeleteMethod, warnings: &mut Vec) -> (u64, usize, usize) { assert!(vector.len() > 1, "Vector length must be bigger than 1(This should be done in previous steps)."); let mut q_index: usize = 0; let mut q_time: u64 = 0; + + let mut gained_space: u64 = 0; + let mut removed_files: usize = 0; + let mut failed_to_remove_files: usize = 0; + match delete_method { DeleteMethod::OneOldest => { for files in vector.iter().enumerate() { @@ -706,8 +718,14 @@ fn delete_files(vector: &[FileEntry], delete_method: &DeleteMethod, errors: &mut } } match fs::remove_file(vector[q_index].path.clone()) { - Ok(_) => (), - Err(_) => errors.push(vector[q_index].path.clone()), + Ok(_) => { + removed_files += 1; + gained_space += vector[q_index].size; + } + Err(_) => { + failed_to_remove_files += 1; + warnings.push("Failed to delete".to_string() + &*vector[q_index].path); + } }; } DeleteMethod::OneNewest => { @@ -719,8 +737,14 @@ fn delete_files(vector: &[FileEntry], delete_method: &DeleteMethod, errors: &mut } } match fs::remove_file(vector[q_index].path.clone()) { - Ok(_) => (), - Err(_) => errors.push(vector[q_index].path.clone()), + Ok(_) => { + removed_files += 1; + gained_space += vector[q_index].size; + } + Err(_) => { + failed_to_remove_files += 1; + warnings.push("Failed to delete".to_string() + &*vector[q_index].path); + } }; } DeleteMethod::AllExceptOldest => { @@ -734,8 +758,14 @@ fn delete_files(vector: &[FileEntry], delete_method: &DeleteMethod, errors: &mut for files in vector.iter().enumerate() { if q_index != files.0 { match fs::remove_file(vector[files.0].path.clone()) { - Ok(_) => (), - Err(_) => errors.push(vector[files.0].path.clone()), + Ok(_) => { + removed_files += 1; + gained_space += vector[files.0].size; + } + Err(_) => { + failed_to_remove_files += 1; + warnings.push("Failed to delete".to_string() + &*vector[files.0].path); + } }; } } @@ -751,8 +781,14 @@ fn delete_files(vector: &[FileEntry], delete_method: &DeleteMethod, errors: &mut for files in vector.iter().enumerate() { if q_index != files.0 { match fs::remove_file(vector[files.0].path.clone()) { - Ok(_) => (), - Err(_) => errors.push(vector[files.0].path.clone()), + Ok(_) => { + removed_files += 1; + gained_space += vector[files.0].size; + } + Err(_) => { + failed_to_remove_files += 1; + warnings.push("Failed to delete".to_string() + &*vector[files.0].path); + } }; } } @@ -761,4 +797,6 @@ fn delete_files(vector: &[FileEntry], delete_method: &DeleteMethod, errors: &mut panic!(); } }; + println!("{} {} {}", gained_space, removed_files, failed_to_remove_files); + (gained_space, removed_files, failed_to_remove_files) } diff --git a/czkawka_gui_orbtk/src/main.rs b/czkawka_gui_orbtk/src/main.rs index bb2fd47..e2ec8ab 100644 --- a/czkawka_gui_orbtk/src/main.rs +++ b/czkawka_gui_orbtk/src/main.rs @@ -16,15 +16,7 @@ fn main() { .columns(Columns::create().push(105.0).push(67.0)) .rows(Rows::create().push(50.0).push(32.0).push(32.0).push(32.0).push(32.0)) .margin((84, 40)) - .child( - TextBlock::new() - .text("Include Directory:") - .v_align("center") - .h_align("start") - .attach(Grid::column(0)) - .attach(Grid::row(0)) - .build(ctx), - ) + .child(TextBlock::new().text("Include Directory:").v_align("center").h_align("start").attach(Grid::column(0)).attach(Grid::row(0)).build(ctx)) .child( TextBox::new() .id("include_directory") @@ -36,15 +28,7 @@ fn main() { .min_width(300.0) .build(ctx), ) - .child( - TextBlock::new() - .text("Exclude Directory:") - .v_align("center") - .h_align("start") - .attach(Grid::column(0)) - .attach(Grid::row(1)) - .build(ctx), - ) + .child(TextBlock::new().text("Exclude Directory:").v_align("center").h_align("start").attach(Grid::column(0)).attach(Grid::row(1)).build(ctx)) .child( TextBox::new() .id("exclude_directory") @@ -56,15 +40,7 @@ fn main() { .min_width(300.0) .build(ctx), ) - .child( - TextBlock::new() - .text("Info:\n\n rr") - .v_align("center") - .h_align("start") - .attach(Grid::column(0)) - .attach(Grid::row(2)) - .build(ctx), - ) + .child(TextBlock::new().text("Info:\n\n rr").v_align("center").h_align("start").attach(Grid::column(0)).attach(Grid::row(2)).build(ctx)) .build(ctx), ) .close_button(false)