1
0
Fork 0
mirror of synced 2024-05-07 14:03:48 +12:00

Add some comments

This commit is contained in:
Rafał Mikrut 2020-09-01 22:48:20 +02:00
parent 9d4de08ece
commit 7eeff49426
4 changed files with 40 additions and 22 deletions

View file

@ -4,30 +4,37 @@ It is in very early development, so most of the functions aren't added and doesn
## Done ## Done
- Basic menu(need refactoring) - Rich instruction with examples - CLI(`cargo run --bin czkawka_cli`)
- Duplicated file finding - CLI - Duplicated file finding - CLI
- Including and excluding directories(absolute pathes) - Including and excluding directories(absolute pathes)
- Option to remove files in different ways - Option to remove files in different ways
- Fast(by size) or accurate(by hash) file checking - Fast(by size) or accurate(by hash) file checking
- Empty folders finding - CLI
- Advanced empty files finding(finds and remove folders which contains only empty folders)
- Option to remove all files
## TODO ## TODO
- Comments - a lot of things should be described
- Tests
- Github CI
- Unit tests(if available)
- Duplicated file finding - CLI - Duplicated file finding - CLI
- saving results to file - saving results to file
- support for * when excluding files and folders - support for * when excluding files and folders
- GUI(GTK) - GUI(GTK)
- Removing empty folders
- Files with debug symbols - Files with debug symbols
- Support for showing only duplicates with specific extension, name(Regex support needed) - Support for showing only duplicates with specific extension, name(Regex support needed)
- Maybe windows support, but this will need some refactoring in code - Maybe windows support, but this will need some refactoring in code
## Usage ## Usage
For now only Linux(and probably also macOS) is supported
- Install requirements for GTK(minimum 3.16) - Install requirements for GTK(minimum 3.16)
``` ```
apt install -y libgtk-3-dev apt install -y libgtk-3-dev
``` ```
- Download source - Download source
``` ```
git clone github/czkawka // TODO git clone https://github.com/qarmin/czkawka.git
cd czkawka cd czkawka
``` ```
- Run GUI(Still WIP) - Run GUI(Still WIP)
@ -35,8 +42,9 @@ cd czkawka
cargo run --bin czkawka_gui cargo run --bin czkawka_gui
``` ```
- Run CLI - Run CLI
```
cargo run --bin czkawka_cli
```
## License ## License
Czkawka is released under the terms of the GNU Lesser General Public License, version 2.1 or, at your option, any later version, as published by the Free Software Foundation. Czkawka is released under the terms of the GNU Lesser General Public License, version 2.1 or, at your option, any later version, as published by the Free Software Foundation.

View file

@ -151,7 +151,7 @@ impl DuplicateFinder {
println!("Include Directory ERROR: Path {} doesn't exists.", directory); println!("Include Directory ERROR: Path {} doesn't exists.", directory);
continue; continue;
} }
if !Path::new(&directory).exists() { if !Path::new(&directory).is_dir() {
println!("Include Directory ERROR: {} isn't folder.", directory); println!("Include Directory ERROR: {} isn't folder.", directory);
continue; continue;
} }
@ -210,7 +210,7 @@ impl DuplicateFinder {
println!("Exclude Directory ERROR: Path {} doesn't exists.", directory); println!("Exclude Directory ERROR: Path {} doesn't exists.", directory);
continue; continue;
} }
if !Path::new(&directory).exists() { if !Path::new(&directory).is_dir() {
println!("Exclude Directory ERROR: {} isn't folder.", directory); println!("Exclude Directory ERROR: {} isn't folder.", directory);
continue; continue;
} }

View file

@ -5,18 +5,22 @@ use std::path::Path;
use std::time::SystemTime; use std::time::SystemTime;
use std::{fs, process}; use std::{fs, process};
/// Enum with values which show if folder is empty.
/// In function "optimize_folders" automatically "Maybe" is changed to "Yes", so it is not necessery to put it here
#[derive(Eq, PartialEq, Copy, Clone)] #[derive(Eq, PartialEq, Copy, Clone)]
enum FolderEmptiness { enum FolderEmptiness {
No, No,
Maybe, Maybe,
} }
/// Struct assigned to each checked folder with parent path(used to ignore parent if children are not empty) and flag which shows if folder is empty
#[derive(Clone)] #[derive(Clone)]
struct FolderEntry { struct FolderEntry {
parent_path: Option<String>, parent_path: Option<String>,
is_empty: FolderEmptiness, is_empty: FolderEmptiness,
} }
/// Struct to store most basics info about all folder
pub struct EmptyFolder { pub struct EmptyFolder {
number_of_checked_folders: usize, number_of_checked_folders: usize,
number_of_empty_folders: usize, number_of_empty_folders: usize,
@ -25,7 +29,9 @@ pub struct EmptyFolder {
included_directories: Vec<String>, included_directories: Vec<String>,
} }
/// Method implementation for EmptyFolder
impl EmptyFolder { impl EmptyFolder {
/// New function providing basics values
pub fn new() -> EmptyFolder { pub fn new() -> EmptyFolder {
EmptyFolder { EmptyFolder {
number_of_checked_folders: 0, number_of_checked_folders: 0,
@ -36,6 +42,7 @@ impl EmptyFolder {
} }
} }
/// Public function used by CLI to search for empty folders
pub fn find_empty_folders(mut self, delete_folders: bool) { pub fn find_empty_folders(mut self, delete_folders: bool) {
self.optimize_directories(); self.optimize_directories();
self.debug_print(); self.debug_print();
@ -68,7 +75,8 @@ impl EmptyFolder {
self.empty_folder_list = new_directory_folders; self.empty_folder_list = new_directory_folders;
} }
/// Function to check if folder are empty, initial_checking is used to check again if folder is /// Function to check if folder are empty.
/// Parameter initial_checking for second check before deleting to be sure that checked folder is still empty
fn check_for_empty_folders(&mut self, initial_checking: bool) { fn check_for_empty_folders(&mut self, initial_checking: bool) {
let start_time: SystemTime = SystemTime::now(); let start_time: SystemTime = SystemTime::now();
let mut folders_to_check: Vec<String> = 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<String> = 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
@ -87,7 +95,7 @@ impl EmptyFolder {
folders_to_check.push(id.clone()); folders_to_check.push(id.clone());
} }
} else { } else {
// Add root folders for finding // Add folders searched before
for id in &self.empty_folder_list { for id in &self.empty_folder_list {
folders_checked.insert( folders_checked.insert(
id.0.clone(), id.0.clone(),
@ -104,7 +112,7 @@ impl EmptyFolder {
let mut next_folder: String; let mut next_folder: String;
while !folders_to_check.is_empty() { while !folders_to_check.is_empty() {
current_folder = folders_to_check.pop().unwrap(); current_folder = folders_to_check.pop().unwrap();
// Checked folder may be deleted so we assume that cannot removed folder be empty
let read_dir = match fs::read_dir(&current_folder) { let read_dir = match fs::read_dir(&current_folder) {
Ok(t) => t, Ok(t) => t,
_ => { _ => {
@ -112,9 +120,11 @@ impl EmptyFolder {
continue; continue;
} }
}; };
for entry in read_dir { for entry in read_dir {
let entry_data = entry.unwrap(); let entry_data = entry.unwrap();
let metadata: Metadata = entry_data.metadata().unwrap(); let metadata: Metadata = entry_data.metadata().unwrap();
// If child is dir, still folder may be considered as empty if all children are only directories.
if metadata.is_dir() { if metadata.is_dir() {
let mut is_excluded_dir = false; let mut is_excluded_dir = false;
next_folder = "".to_owned() + &current_folder + &entry_data.file_name().into_string().unwrap() + "/"; next_folder = "".to_owned() + &current_folder + &entry_data.file_name().into_string().unwrap() + "/";
@ -136,7 +146,7 @@ impl EmptyFolder {
); );
} }
} else { } else {
// Not folder so it may be a file or symbolic link // Not folder so it may be a file or symbolic link so it isn't empty
folders_checked.get_mut(&current_folder).unwrap().is_empty = FolderEmptiness::No; folders_checked.get_mut(&current_folder).unwrap().is_empty = FolderEmptiness::No;
let mut d = folders_checked.get_mut(&current_folder).unwrap(); let mut d = folders_checked.get_mut(&current_folder).unwrap();
let mut cf: String; let mut cf: String;
@ -153,13 +163,14 @@ impl EmptyFolder {
} }
} }
if initial_checking { if initial_checking {
// We need to set empty folder list
for entry in folders_checked { for entry in folders_checked {
if entry.1.is_empty != FolderEmptiness::No { if entry.1.is_empty != FolderEmptiness::No {
self.empty_folder_list.insert(entry.0, entry.1); self.empty_folder_list.insert(entry.0, entry.1);
} }
} }
} else { } else {
// Sprawdzenie // We need to check if parent of folder isn't also empty, because we wan't to delete only parent with two empty folders except this folders and at the end parent folder
let mut new_folders_list: HashMap<String, FolderEntry> = Default::default(); let mut new_folders_list: HashMap<String, FolderEntry> = Default::default();
for entry in folders_checked { for entry in folders_checked {
if entry.1.is_empty != FolderEmptiness::No && self.empty_folder_list.contains_key(&entry.0) { if entry.1.is_empty != FolderEmptiness::No && self.empty_folder_list.contains_key(&entry.0) {
@ -172,9 +183,11 @@ impl EmptyFolder {
Common::print_time(start_time, SystemTime::now(), "check_for_empty_folder".to_string()); Common::print_time(start_time, SystemTime::now(), "check_for_empty_folder".to_string());
} }
/// Deletes earlier finded empty folders
fn delete_empty_folders(&self) { fn delete_empty_folders(&self) {
let start_time: SystemTime = SystemTime::now(); let start_time: SystemTime = SystemTime::now();
let mut errors: Vec<String> = Vec::new(); let mut errors: Vec<String> = Vec::new();
// Folders may be deleted or require too big privileges
for entry in &self.empty_folder_list { for entry in &self.empty_folder_list {
match fs::remove_dir_all(entry.0) { match fs::remove_dir_all(entry.0) {
Ok(_) => (), Ok(_) => (),
@ -192,6 +205,7 @@ impl EmptyFolder {
Common::print_time(start_time, SystemTime::now(), "delete_files".to_string()); Common::print_time(start_time, SystemTime::now(), "delete_files".to_string());
} }
/// Prints basic info about empty folders
fn print_empty_folders(&self) { fn print_empty_folders(&self) {
if !self.empty_folder_list.is_empty() { if !self.empty_folder_list.is_empty() {
println!("Found {} empty folders", self.empty_folder_list.len()); println!("Found {} empty folders", self.empty_folder_list.len());
@ -201,6 +215,7 @@ impl EmptyFolder {
} }
} }
/// Debug print
fn debug_print(&self) { fn debug_print(&self) {
if false { if false {
println!("---------------DEBUG PRINT---------------"); println!("---------------DEBUG PRINT---------------");
@ -216,6 +231,7 @@ impl EmptyFolder {
} }
// TODO maybe move this and one from duplicated finder to one common class to avoid duplicating code // TODO maybe move this and one from duplicated finder to one common class to avoid duplicating code
/// Optimize include and exclude directories by removing duplicates etc.
fn optimize_directories(&mut self) { fn optimize_directories(&mut self) {
let start_time: SystemTime = SystemTime::now(); let start_time: SystemTime = SystemTime::now();
@ -333,6 +349,8 @@ impl EmptyFolder {
self.included_directories.sort(); self.included_directories.sort();
Common::print_time(start_time, SystemTime::now(), "optimize_directories".to_string()); Common::print_time(start_time, SystemTime::now(), "optimize_directories".to_string());
} }
/// Set include dir which needst to be relative, exists,
pub fn set_include_directory(&mut self, mut include_directory: String) { pub fn set_include_directory(&mut self, mut include_directory: String) {
// let start_time: SystemTime = SystemTime::now(); // let start_time: SystemTime = SystemTime::now();
@ -369,7 +387,7 @@ impl EmptyFolder {
println!("Include Directory ERROR: Path {} doesn't exists.", directory); println!("Include Directory ERROR: Path {} doesn't exists.", directory);
continue; continue;
} }
if !Path::new(&directory).exists() { if !Path::new(&directory).is_dir() {
println!("Include Directory ERROR: {} isn't folder.", directory); println!("Include Directory ERROR: {} isn't folder.", directory);
continue; continue;
} }
@ -428,7 +446,7 @@ impl EmptyFolder {
println!("Exclude Directory ERROR: Path {} doesn't exists.", directory); println!("Exclude Directory ERROR: Path {} doesn't exists.", directory);
continue; continue;
} }
if !Path::new(&directory).exists() { if !Path::new(&directory).is_dir() {
println!("Exclude Directory ERROR: {} isn't folder.", directory); println!("Exclude Directory ERROR: {} isn't folder.", directory);
continue; continue;
} }

View file

@ -1,11 +1,3 @@
pub mod common; pub mod common;
pub mod duplicate; pub mod duplicate;
pub mod empty_folder; pub mod empty_folder;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}