1
0
Fork 0
mirror of synced 2024-05-03 03:52:58 +12:00

Improve code quality. (#52)

* Remove verbose constructs in core.

* Use self and const fn where appropriate.

* Remove needless borrows.

* Fix name in function arguments.

* Merge 'master' into quality

* Decrease function complexity.

* Run fmt.

* Fix clippy.

* Fix duplicate extension files.

* Fix excluded items.

* Fix allowed extensions (Part 2).

* Fix temporary files.
This commit is contained in:
Caduser2020 2020-10-09 15:32:08 -05:00 committed by GitHub
parent 196411c101
commit 085da0369e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 194 additions and 367 deletions

View file

@ -19,6 +19,7 @@ pub struct FileEntry {
} }
/// Info struck with helpful information's about results /// Info struck with helpful information's about results
#[derive(Default)]
pub struct Info { pub struct Info {
pub number_of_checked_files: usize, pub number_of_checked_files: usize,
pub number_of_checked_folders: usize, pub number_of_checked_folders: usize,
@ -27,22 +28,10 @@ pub struct Info {
pub taken_space: u64, pub taken_space: u64,
pub number_of_real_files: usize, pub number_of_real_files: usize,
} }
impl Info {
pub fn new() -> Info {
Info {
number_of_checked_files: 0,
number_of_checked_folders: 0,
number_of_ignored_files: 0,
number_of_ignored_things: 0,
taken_space: 0,
number_of_real_files: 0,
}
}
}
impl Default for Info { impl Info {
fn default() -> Self { pub fn new() -> Self {
Self::new() Default::default()
} }
} }
@ -59,8 +48,8 @@ pub struct BigFile {
} }
impl BigFile { impl BigFile {
pub fn new() -> BigFile { pub fn new() -> Self {
BigFile { Self {
text_messages: Default::default(), text_messages: Default::default(),
information: Info::new(), information: Info::new(),
big_files: Default::default(), big_files: Default::default(),
@ -78,15 +67,15 @@ impl BigFile {
self.debug_print(); self.debug_print();
} }
pub fn get_big_files(&self) -> &BTreeMap<u64, Vec<FileEntry>> { pub const fn get_big_files(&self) -> &BTreeMap<u64, Vec<FileEntry>> {
&self.big_files &self.big_files
} }
pub fn get_text_messages(&self) -> &Messages { pub const fn get_text_messages(&self) -> &Messages {
&self.text_messages &self.text_messages
} }
pub fn get_information(&self) -> &Info { pub const fn get_information(&self) -> &Info {
&self.information &self.information
} }
@ -121,7 +110,7 @@ impl BigFile {
continue; continue;
} // Permissions denied } // Permissions denied
}; };
for entry in read_dir { 'dir: for entry in read_dir {
let entry_data = match entry { let entry_data = match entry {
Ok(t) => t, Ok(t) => t,
Err(_) => { Err(_) => {
@ -147,7 +136,6 @@ impl BigFile {
continue; continue;
} }
let mut is_excluded_dir = false;
next_folder = "".to_owned() next_folder = "".to_owned()
+ &current_folder + &current_folder
+ match &entry_data.file_name().into_string() { + match &entry_data.file_name().into_string() {
@ -158,25 +146,16 @@ impl BigFile {
for ed in &self.directories.excluded_directories { for ed in &self.directories.excluded_directories {
if next_folder == *ed { if next_folder == *ed {
is_excluded_dir = true; continue 'dir;
break;
} }
} }
if !is_excluded_dir { for expression in &self.excluded_items.items {
let mut found_expression: bool = false; if Common::regex_check(expression, &next_folder) {
for expression in &self.excluded_items.items { continue 'dir;
if Common::regex_check(expression, &next_folder) {
found_expression = true;
break;
}
} }
if found_expression {
break;
}
folders_to_check.push(next_folder);
} }
folders_to_check.push(next_folder);
} else if metadata.is_file() { } else if metadata.is_file() {
let mut have_valid_extension: bool;
let file_name_lowercase: String = match entry_data.file_name().into_string() { let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t, Ok(t) => t,
Err(_) => continue, Err(_) => continue,
@ -184,65 +163,50 @@ impl BigFile {
.to_lowercase(); .to_lowercase();
// Checking allowed extensions // Checking allowed extensions
if !self.allowed_extensions.file_extensions.is_empty() { let allowed = self.allowed_extensions.file_extensions.iter().any(|e| file_name_lowercase.ends_with((".".to_string() + e.to_lowercase().as_str()).as_str()));
have_valid_extension = false; if !allowed {
for extension in &self.allowed_extensions.file_extensions { // Not an allowed extension, ignore it.
if file_name_lowercase.ends_with((".".to_string() + extension.to_lowercase().as_str()).as_str()) { self.information.number_of_ignored_files += 1;
have_valid_extension = true; continue 'dir;
break;
}
}
} else {
have_valid_extension = true;
} }
// Checking files // Checking files
if have_valid_extension { let current_file_name = "".to_owned()
let current_file_name = "".to_owned() + &current_folder
+ &current_folder + match &entry_data.file_name().into_string() {
+ match &entry_data.file_name().into_string() { Ok(t) => t,
Ok(t) => t, Err(_) => continue,
Err(_) => continue,
};
// Checking expressions
let mut found_expression: bool = false;
for expression in &self.excluded_items.items {
if Common::regex_check(expression, &current_file_name) {
found_expression = true;
break;
}
}
if found_expression {
break;
}
// Creating new file entry
let fe: FileEntry = FileEntry {
path: current_file_name.clone(),
size: metadata.len(),
modified_date: match metadata.modified() {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_) => {
self.text_messages.warnings.push(format!("File {} seems to be modified before Unix Epoch.", current_file_name));
0
}
},
Err(_) => {
self.text_messages.warnings.push("Unable to get modification date from file ".to_string() + current_file_name.as_str());
continue;
} // Permissions Denied
},
}; };
self.big_files.entry(metadata.len()).or_insert_with(Vec::new); // Checking expressions
self.big_files.get_mut(&metadata.len()).unwrap().push(fe); for expression in &self.excluded_items.items {
if Common::regex_check(expression, &current_file_name) {
self.information.number_of_checked_files += 1; continue 'dir;
} else { }
self.information.number_of_ignored_files += 1;
} }
// Creating new file entry
let fe: FileEntry = FileEntry {
path: current_file_name.clone(),
size: metadata.len(),
modified_date: match metadata.modified() {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_) => {
self.text_messages.warnings.push(format!("File {} seems to be modified before Unix Epoch.", current_file_name));
0
}
},
Err(_) => {
self.text_messages.warnings.push("Unable to get modification date from file ".to_string() + current_file_name.as_str());
continue;
} // Permissions Denied
},
};
self.big_files.entry(metadata.len()).or_insert_with(Vec::new);
self.big_files.get_mut(&metadata.len()).unwrap().push(fe);
self.information.number_of_checked_files += 1;
} else { } else {
// Probably this is symbolic links so we are free to ignore this // Probably this is symbolic links so we are free to ignore this
self.information.number_of_ignored_things += 1; self.information.number_of_ignored_things += 1;

View file

@ -7,9 +7,10 @@ use std::time::SystemTime;
pub struct Common(); pub struct Common();
impl Common { impl Common {
/// Printing time which took between start and stop point and prints also function name /// Printing time which took between start and stop point and prints also function name
pub fn print_time(_start_time: SystemTime, _end_time: SystemTime, _function_name: String) { #[allow(unused_variables)]
pub fn print_time(start_time: SystemTime, end_time: SystemTime, function_name: String) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
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."));
} }
pub fn delete_multiple_entries(entries: &[String]) -> Vec<String> { pub fn delete_multiple_entries(entries: &[String]) -> Vec<String> {

View file

@ -3,16 +3,14 @@ use crate::common_messages::Messages;
use std::path::Path; use std::path::Path;
use std::time::SystemTime; use std::time::SystemTime;
#[derive(Default)]
pub struct Directories { pub struct Directories {
pub excluded_directories: Vec<String>, pub excluded_directories: Vec<String>,
pub included_directories: Vec<String>, pub included_directories: Vec<String>,
} }
impl Directories { impl Directories {
pub fn new() -> Directories { pub fn new() -> Self {
Directories { Default::default()
excluded_directories: vec![],
included_directories: vec![],
}
} }
/// Setting included directories, at least one must be provided /// Setting included directories, at least one must be provided
@ -244,9 +242,3 @@ impl Directories {
true true
} }
} }
impl Default for Directories {
fn default() -> Self {
Self::new()
}
}

View file

@ -2,13 +2,14 @@ use crate::common::Common;
use crate::common_messages::Messages; use crate::common_messages::Messages;
use std::time::SystemTime; use std::time::SystemTime;
#[derive(Default)]
pub struct Extensions { pub struct Extensions {
pub file_extensions: Vec<String>, pub file_extensions: Vec<String>,
} }
impl Extensions { impl Extensions {
pub fn new() -> Extensions { pub fn new() -> Self {
Extensions { file_extensions: vec![] } Default::default()
} }
/// List of allowed extensions, only files with this extensions will be checking if are duplicates /// List of allowed extensions, only files with this extensions will be checking if are duplicates
/// After, extensions cannot contains any dot, commas etc. /// After, extensions cannot contains any dot, commas etc.
@ -48,8 +49,3 @@ impl Extensions {
Common::print_time(start_time, SystemTime::now(), "set_allowed_extensions".to_string()); Common::print_time(start_time, SystemTime::now(), "set_allowed_extensions".to_string());
} }
} }
impl Default for Extensions {
fn default() -> Self {
Self::new()
}
}

View file

@ -2,13 +2,14 @@ use crate::common::Common;
use crate::common_messages::Messages; use crate::common_messages::Messages;
use std::time::SystemTime; use std::time::SystemTime;
#[derive(Default)]
pub struct ExcludedItems { pub struct ExcludedItems {
pub items: Vec<String>, pub items: Vec<String>,
} }
impl ExcludedItems { impl ExcludedItems {
pub fn new() -> ExcludedItems { pub fn new() -> Self {
ExcludedItems { items: vec![] } Default::default()
} }
/// Setting excluded items which needs to contains * wildcard /// Setting excluded items which needs to contains * wildcard
/// Are a lot of slower than absolute path, so it should be used to heavy /// Are a lot of slower than absolute path, so it should be used to heavy
@ -45,8 +46,3 @@ impl ExcludedItems {
Common::print_time(start_time, SystemTime::now(), "set_excluded_items".to_string()); Common::print_time(start_time, SystemTime::now(), "set_excluded_items".to_string());
} }
} }
impl Default for ExcludedItems {
fn default() -> Self {
Self::new()
}
}

View file

@ -1,3 +1,4 @@
#[derive(Default)]
pub struct Messages { pub struct Messages {
pub messages: Vec<String>, pub messages: Vec<String>,
pub warnings: Vec<String>, pub warnings: Vec<String>,
@ -5,12 +6,8 @@ pub struct Messages {
} }
impl Messages { impl Messages {
pub fn new() -> Messages { pub fn new() -> Self {
Messages { Default::default()
messages: vec![],
warnings: vec![],
errors: vec![],
}
} }
pub fn print_messages(&self) { pub fn print_messages(&self) {
if !self.messages.is_empty() { if !self.messages.is_empty() {
@ -40,8 +37,3 @@ impl Messages {
} }
} }
} }
impl Default for Messages {
fn default() -> Self {
Self::new()
}
}

View file

@ -39,6 +39,7 @@ pub struct FileEntry {
} }
/// Info struck with helpful information's about results /// Info struck with helpful information's about results
#[derive(Default)]
pub struct Info { pub struct Info {
pub number_of_checked_files: usize, pub number_of_checked_files: usize,
pub number_of_checked_folders: usize, pub number_of_checked_folders: usize,
@ -55,30 +56,10 @@ pub struct Info {
pub number_of_failed_to_remove_files: usize, pub number_of_failed_to_remove_files: usize,
pub gained_space: u64, pub gained_space: u64,
} }
impl Info {
pub fn new() -> Info {
Info {
number_of_checked_files: 0,
number_of_ignored_files: 0,
number_of_checked_folders: 0,
number_of_ignored_things: 0,
number_of_groups_by_size: 0,
number_of_duplicated_files_by_size: 0,
number_of_groups_by_hash: 0,
number_of_duplicated_files_by_hash: 0,
lost_space_by_size: 0,
lost_space_by_hash: 0,
bytes_read_when_hashing: 0,
number_of_removed_files: 0,
number_of_failed_to_remove_files: 0,
gained_space: 0,
}
}
}
impl Default for Info { impl Info {
fn default() -> Self { pub fn new() -> Self {
Self::new() Default::default()
} }
} }
@ -98,8 +79,8 @@ pub struct DuplicateFinder {
} }
impl DuplicateFinder { impl DuplicateFinder {
pub fn new() -> DuplicateFinder { pub fn new() -> Self {
DuplicateFinder { Self {
text_messages: Messages::new(), text_messages: Messages::new(),
information: Info::new(), information: Info::new(),
files_with_identical_size: Default::default(), files_with_identical_size: Default::default(),
@ -125,23 +106,23 @@ impl DuplicateFinder {
self.debug_print(); self.debug_print();
} }
pub fn get_check_method(&self) -> &CheckingMethod { pub const fn get_check_method(&self) -> &CheckingMethod {
&self.check_method &self.check_method
} }
pub fn get_files_sorted_by_size(&self) -> &BTreeMap<u64, Vec<FileEntry>> { pub const fn get_files_sorted_by_size(&self) -> &BTreeMap<u64, Vec<FileEntry>> {
&self.files_with_identical_size &self.files_with_identical_size
} }
pub fn get_files_sorted_by_hash(&self) -> &BTreeMap<u64, Vec<Vec<FileEntry>>> { pub const fn get_files_sorted_by_hash(&self) -> &BTreeMap<u64, Vec<Vec<FileEntry>>> {
&self.files_with_identical_hashes &self.files_with_identical_hashes
} }
pub fn get_text_messages(&self) -> &Messages { pub const fn get_text_messages(&self) -> &Messages {
&self.text_messages &self.text_messages
} }
pub fn get_information(&self) -> &Info { pub const fn get_information(&self) -> &Info {
&self.information &self.information
} }
@ -207,7 +188,7 @@ impl DuplicateFinder {
}; };
// Check every sub folder/file/link etc. // Check every sub folder/file/link etc.
for entry in read_dir { 'dir: for entry in read_dir {
let entry_data = match entry { let entry_data = match entry {
Ok(t) => t, Ok(t) => t,
Err(_) => { Err(_) => {
@ -233,7 +214,6 @@ impl DuplicateFinder {
continue; continue;
} }
let mut is_excluded_dir = false;
next_folder = "".to_owned() next_folder = "".to_owned()
+ &current_folder + &current_folder
+ match &entry_data.file_name().into_string() { + match &entry_data.file_name().into_string() {
@ -244,25 +224,17 @@ impl DuplicateFinder {
for ed in &self.directories.excluded_directories { for ed in &self.directories.excluded_directories {
if next_folder == *ed { if next_folder == *ed {
is_excluded_dir = true; continue 'dir;
break;
} }
} }
if !is_excluded_dir { for expression in &self.excluded_items.items {
let mut found_expression: bool = false; if Common::regex_check(expression, &next_folder) {
for expression in &self.excluded_items.items { continue 'dir;
if Common::regex_check(expression, &next_folder) {
found_expression = true;
break;
}
} }
if found_expression {
break;
}
folders_to_check.push(next_folder);
} }
folders_to_check.push(next_folder);
} else if metadata.is_file() { } else if metadata.is_file() {
let mut have_valid_extension: bool; // let mut have_valid_extension: bool;
let file_name_lowercase: String = match entry_data.file_name().into_string() { let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t, Ok(t) => t,
Err(_) => continue, Err(_) => continue,
@ -270,20 +242,14 @@ impl DuplicateFinder {
.to_lowercase(); .to_lowercase();
// Checking allowed extensions // Checking allowed extensions
if !self.allowed_extensions.file_extensions.is_empty() { let allowed = self.allowed_extensions.file_extensions.iter().any(|e| file_name_lowercase.ends_with((".".to_string() + e.to_lowercase().as_str()).as_str()));
have_valid_extension = false; if !allowed {
for extension in &self.allowed_extensions.file_extensions { // Not an allowed extension, ignore it.
if file_name_lowercase.ends_with((".".to_string() + extension.to_lowercase().as_str()).as_str()) { self.information.number_of_ignored_files += 1;
have_valid_extension = true; continue 'dir;
break;
}
}
} else {
have_valid_extension = true;
} }
// Checking files // Checking files
if metadata.len() >= self.minimal_file_size && have_valid_extension { if metadata.len() >= self.minimal_file_size {
let current_file_name = "".to_owned() let current_file_name = "".to_owned()
+ &current_folder + &current_folder
+ match &entry_data.file_name().into_string() { + match &entry_data.file_name().into_string() {
@ -292,16 +258,11 @@ impl DuplicateFinder {
}; };
// Checking expressions // Checking expressions
let mut found_expression: bool = false;
for expression in &self.excluded_items.items { for expression in &self.excluded_items.items {
if Common::regex_check(expression, &current_file_name) { if Common::regex_check(expression, &current_file_name) {
found_expression = true; continue 'dir;
break;
} }
} }
if found_expression {
break;
}
// Creating new file entry // Creating new file entry
let fe: FileEntry = FileEntry { let fe: FileEntry = FileEntry {
@ -328,6 +289,7 @@ impl DuplicateFinder {
self.information.number_of_checked_files += 1; self.information.number_of_checked_files += 1;
} else { } else {
// Probably this is symbolic links so we are free to ignore this
self.information.number_of_ignored_files += 1; self.information.number_of_ignored_files += 1;
} }
} else { } else {

View file

@ -23,6 +23,7 @@ pub struct FileEntry {
} }
/// Info struck with helpful information's about results /// Info struck with helpful information's about results
#[derive(Default)]
pub struct Info { pub struct Info {
pub number_of_checked_files: usize, pub number_of_checked_files: usize,
pub number_of_checked_folders: usize, pub number_of_checked_folders: usize,
@ -33,22 +34,8 @@ pub struct Info {
pub number_of_failed_to_remove_files: usize, pub number_of_failed_to_remove_files: usize,
} }
impl Info { impl Info {
pub fn new() -> Info { pub fn new() -> Self {
Info { Default::default()
number_of_checked_files: 0,
number_of_ignored_files: 0,
number_of_checked_folders: 0,
number_of_ignored_things: 0,
number_of_empty_files: 0,
number_of_removed_files: 0,
number_of_failed_to_remove_files: 0,
}
}
}
impl Default for Info {
fn default() -> Self {
Self::new()
} }
} }
@ -65,8 +52,8 @@ pub struct EmptyFiles {
} }
impl EmptyFiles { impl EmptyFiles {
pub fn new() -> EmptyFiles { pub fn new() -> Self {
EmptyFiles { Self {
text_messages: Messages::new(), text_messages: Messages::new(),
information: Info::new(), information: Info::new(),
recursive_search: true, recursive_search: true,
@ -86,15 +73,15 @@ impl EmptyFiles {
self.debug_print(); self.debug_print();
} }
pub fn get_empty_files(&self) -> &Vec<FileEntry> { pub const fn get_empty_files(&self) -> &Vec<FileEntry> {
&self.empty_files &self.empty_files
} }
pub fn get_text_messages(&self) -> &Messages { pub const fn get_text_messages(&self) -> &Messages {
&self.text_messages &self.text_messages
} }
pub fn get_information(&self) -> &Info { pub const fn get_information(&self) -> &Info {
&self.information &self.information
} }
@ -147,7 +134,7 @@ impl EmptyFiles {
}; };
// Check every sub folder/file/link etc. // Check every sub folder/file/link etc.
for entry in read_dir { 'dir: for entry in read_dir {
let entry_data = match entry { let entry_data = match entry {
Ok(t) => t, Ok(t) => t,
Err(_) => { Err(_) => {
@ -173,7 +160,6 @@ impl EmptyFiles {
continue; continue;
} }
let mut is_excluded_dir = false;
next_folder = "".to_owned() next_folder = "".to_owned()
+ &current_folder + &current_folder
+ match &entry_data.file_name().into_string() { + match &entry_data.file_name().into_string() {
@ -184,25 +170,16 @@ impl EmptyFiles {
for ed in &self.directories.excluded_directories { for ed in &self.directories.excluded_directories {
if next_folder == *ed { if next_folder == *ed {
is_excluded_dir = true; continue 'dir;
break;
} }
} }
if !is_excluded_dir { for expression in &self.excluded_items.items {
let mut found_expression: bool = false; if Common::regex_check(expression, &next_folder) {
for expression in &self.excluded_items.items { continue 'dir;
if Common::regex_check(expression, &next_folder) {
found_expression = true;
break;
}
} }
if found_expression {
break;
}
folders_to_check.push(next_folder);
} }
folders_to_check.push(next_folder);
} else if metadata.is_file() { } else if metadata.is_file() {
let mut have_valid_extension: bool;
let file_name_lowercase: String = match entry_data.file_name().into_string() { let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t, Ok(t) => t,
Err(_) => continue, Err(_) => continue,
@ -210,20 +187,14 @@ impl EmptyFiles {
.to_lowercase(); .to_lowercase();
// Checking allowed extensions // Checking allowed extensions
if !self.allowed_extensions.file_extensions.is_empty() { let allowed = self.allowed_extensions.file_extensions.iter().any(|e| file_name_lowercase.ends_with((".".to_string() + e.to_lowercase().as_str()).as_str()));
have_valid_extension = false; if !allowed {
for extension in &self.allowed_extensions.file_extensions { // Not an allowed extension, ignore it.
if file_name_lowercase.ends_with((".".to_string() + extension.to_lowercase().as_str()).as_str()) { self.information.number_of_ignored_files += 1;
have_valid_extension = true; continue 'dir;
break;
}
}
} else {
have_valid_extension = true;
} }
// Checking files // Checking files
if metadata.len() == 0 && have_valid_extension { if metadata.len() == 0 {
let current_file_name = "".to_owned() let current_file_name = "".to_owned()
+ &current_folder + &current_folder
+ match &entry_data.file_name().into_string() { + match &entry_data.file_name().into_string() {
@ -232,16 +203,11 @@ impl EmptyFiles {
}; };
// Checking expressions // Checking expressions
let mut found_expression: bool = false;
for expression in &self.excluded_items.items { for expression in &self.excluded_items.items {
if Common::regex_check(expression, &current_file_name) { if Common::regex_check(expression, &current_file_name) {
found_expression = true; continue 'dir;
break;
} }
} }
if found_expression {
break;
}
// Creating new file entry // Creating new file entry
let fe: FileEntry = FileEntry { let fe: FileEntry = FileEntry {

View file

@ -34,29 +34,22 @@ pub struct EmptyFolder {
} }
/// Info struck with helpful information's about results /// Info struck with helpful information's about results
#[derive(Default)]
pub struct Info { pub struct Info {
number_of_checked_folders: usize, number_of_checked_folders: usize,
pub number_of_empty_folders: usize, pub number_of_empty_folders: usize,
} }
impl Info { impl Info {
pub fn new() -> Info { pub fn new() -> Self {
Info { Default::default()
number_of_checked_folders: 0,
number_of_empty_folders: 0,
}
} }
} }
impl Default for Info {
fn default() -> Self {
Self::new()
}
}
/// Method implementation for EmptyFolder /// Method implementation for EmptyFolder
impl EmptyFolder { impl EmptyFolder {
/// New function providing basics values /// New function providing basics values
pub fn new() -> EmptyFolder { pub fn new() -> Self {
EmptyFolder { Self {
information: Default::default(), information: Default::default(),
delete_folders: false, delete_folders: false,
text_messages: Messages::new(), text_messages: Messages::new(),
@ -65,14 +58,14 @@ impl EmptyFolder {
} }
} }
pub fn get_empty_folder_list(&self) -> &BTreeMap<String, FolderEntry> { pub const fn get_empty_folder_list(&self) -> &BTreeMap<String, FolderEntry> {
&self.empty_folder_list &self.empty_folder_list
} }
pub fn get_text_messages(&self) -> &Messages { pub const fn get_text_messages(&self) -> &Messages {
&self.text_messages &self.text_messages
} }
pub fn get_information(&self) -> &Info { pub const fn get_information(&self) -> &Info {
&self.information &self.information
} }

View file

@ -22,6 +22,7 @@ pub struct FileEntry {
} }
/// Info struck with helpful information's about results /// Info struck with helpful information's about results
#[derive(Default)]
pub struct Info { pub struct Info {
pub number_of_checked_files: usize, pub number_of_checked_files: usize,
pub number_of_checked_folders: usize, pub number_of_checked_folders: usize,
@ -32,22 +33,8 @@ pub struct Info {
pub number_of_failed_to_remove_files: usize, pub number_of_failed_to_remove_files: usize,
} }
impl Info { impl Info {
pub fn new() -> Info { pub fn new() -> Self {
Info { Default::default()
number_of_checked_files: 0,
number_of_ignored_files: 0,
number_of_checked_folders: 0,
number_of_ignored_things: 0,
number_of_temporary_files: 0,
number_of_removed_files: 0,
number_of_failed_to_remove_files: 0,
}
}
}
impl Default for Info {
fn default() -> Self {
Self::new()
} }
} }
@ -63,8 +50,8 @@ pub struct Temporary {
} }
impl Temporary { impl Temporary {
pub fn new() -> Temporary { pub fn new() -> Self {
Temporary { Self {
text_messages: Messages::new(), text_messages: Messages::new(),
information: Info::new(), information: Info::new(),
recursive_search: true, recursive_search: true,
@ -83,14 +70,14 @@ impl Temporary {
self.debug_print(); self.debug_print();
} }
pub fn get_temporary_files(&self) -> &Vec<FileEntry> { pub const fn get_temporary_files(&self) -> &Vec<FileEntry> {
&self.temporary_files &self.temporary_files
} }
pub fn get_text_messages(&self) -> &Messages { pub const fn get_text_messages(&self) -> &Messages {
&self.text_messages &self.text_messages
} }
pub fn get_information(&self) -> &Info { pub const fn get_information(&self) -> &Info {
&self.information &self.information
} }
@ -139,7 +126,7 @@ impl Temporary {
}; };
// Check every sub folder/file/link etc. // Check every sub folder/file/link etc.
for entry in read_dir { 'dir: for entry in read_dir {
let entry_data = match entry { let entry_data = match entry {
Ok(t) => t, Ok(t) => t,
Err(_) => { Err(_) => {
@ -165,7 +152,6 @@ impl Temporary {
continue; continue;
} }
let mut is_excluded_dir = false;
next_folder = "".to_owned() next_folder = "".to_owned()
+ &current_folder + &current_folder
+ match &entry_data.file_name().into_string() { + match &entry_data.file_name().into_string() {
@ -176,88 +162,67 @@ impl Temporary {
for ed in &self.directories.excluded_directories { for ed in &self.directories.excluded_directories {
if next_folder == *ed { if next_folder == *ed {
is_excluded_dir = true; continue 'dir;
break;
} }
} }
if !is_excluded_dir { for expression in &self.excluded_items.items {
let mut found_expression: bool = false; if Common::regex_check(expression, &next_folder) {
for expression in &self.excluded_items.items { continue 'dir;
if Common::regex_check(expression, &next_folder) {
found_expression = true;
break;
}
} }
if found_expression {
break;
}
folders_to_check.push(next_folder);
} }
folders_to_check.push(next_folder);
} else if metadata.is_file() { } else if metadata.is_file() {
let file_name_lowercase: String = match entry_data.file_name().into_string() { let file_name_lowercase: String = match entry_data.file_name().into_string() {
Ok(t) => t, Ok(t) => t,
Err(_) => continue, Err(_) => continue,
} }
.to_lowercase(); .to_lowercase();
let mut is_temporary_file: bool = false;
// Temporary files which needs to have dot in name(not sure if exists without dot) // Temporary files which needs to have dot in name(not sure if exists without dot)
let temporary_with_dot = ["#", "thumbs.db", ".bak", "~", ".tmp", ".temp", ".ds_store", ".crdownload", ".part", ".cache", ".dmp", ".download", ".partial"]; let temporary_with_dot = ["#", "thumbs.db", ".bak", "~", ".tmp", ".temp", ".ds_store", ".crdownload", ".part", ".cache", ".dmp", ".download", ".partial"];
if file_name_lowercase.contains('.') { if !file_name_lowercase.contains('.') || !temporary_with_dot.iter().any(|f| file_name_lowercase.ends_with(f)) {
for temp in temporary_with_dot.iter() { self.information.number_of_ignored_files += 1;
if file_name_lowercase.ends_with(temp) { continue 'dir;
is_temporary_file = true;
}
}
} }
// Checking files // Checking files
if is_temporary_file { let current_file_name = "".to_owned()
let current_file_name = "".to_owned() + &current_folder
+ &current_folder + match &entry_data.file_name().into_string() {
+ match &entry_data.file_name().into_string() { Ok(t) => t,
Ok(t) => t, Err(_) => continue,
Err(_) => continue,
};
// Checking expressions
let mut found_expression: bool = false;
for expression in &self.excluded_items.items {
if Common::regex_check(expression, &current_file_name) {
found_expression = true;
break;
}
}
if found_expression {
break;
}
// Creating new file entry
let fe: FileEntry = FileEntry {
path: current_file_name.clone(),
modified_date: match metadata.modified() {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_) => {
self.text_messages.warnings.push(format!("File {} seems to be modified before Unix Epoch.", current_file_name));
0
}
},
Err(_) => {
self.text_messages.warnings.push("Unable to get modification date from file ".to_string() + current_file_name.as_str());
continue;
} // Permissions Denied
},
}; };
// Adding files to Vector // Checking expressions
self.temporary_files.push(fe); for expression in &self.excluded_items.items {
if Common::regex_check(expression, &current_file_name) {
self.information.number_of_checked_files += 1; continue 'dir;
} else { }
self.information.number_of_ignored_files += 1;
} }
// Creating new file entry
let fe: FileEntry = FileEntry {
path: current_file_name.clone(),
modified_date: match metadata.modified() {
Ok(t) => match t.duration_since(UNIX_EPOCH) {
Ok(d) => d.as_secs(),
Err(_) => {
self.text_messages.warnings.push(format!("File {} seems to be modified before Unix Epoch.", current_file_name));
0
}
},
Err(_) => {
self.text_messages.warnings.push("Unable to get modification date from file ".to_string() + current_file_name.as_str());
continue;
} // Permissions Denied
},
};
// Adding files to Vector
self.temporary_files.push(fe);
self.information.number_of_checked_files += 1;
} else { } else {
// Probably this is symbolic links so we are free to ignore this // Probably this is symbolic links so we are free to ignore this
self.information.number_of_ignored_things += 1; self.information.number_of_ignored_things += 1;

View file

@ -586,12 +586,12 @@ fn main() {
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data // Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
for tree_path in selection_rows.iter().rev() { for tree_path in selection_rows.iter().rev() {
let name = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsDuplicates::Name as i32).get::<String>().unwrap().unwrap(); let name = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsDuplicates::Name as i32).get::<String>().unwrap().unwrap();
let path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsDuplicates::Path as i32).get::<String>().unwrap().unwrap(); let path = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsDuplicates::Path as i32).get::<String>().unwrap().unwrap();
match fs::remove_file(format!("{}/{}", path, name)) { match fs::remove_file(format!("{}/{}", path, name)) {
Ok(_) => { Ok(_) => {
list_store.remove(&list_store.get_iter(&tree_path).unwrap()); list_store.remove(&list_store.get_iter(tree_path).unwrap());
} }
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(), Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
} }
@ -613,12 +613,12 @@ fn main() {
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data // Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
for tree_path in selection_rows.iter().rev() { for tree_path in selection_rows.iter().rev() {
let name = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsEmptyFolders::Name as i32).get::<String>().unwrap().unwrap(); let name = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsEmptyFolders::Name as i32).get::<String>().unwrap().unwrap();
let path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsEmptyFolders::Path as i32).get::<String>().unwrap().unwrap(); let path = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsEmptyFolders::Path as i32).get::<String>().unwrap().unwrap();
match fs::remove_dir(format!("{}/{}", path, name)) { match fs::remove_dir(format!("{}/{}", path, name)) {
Ok(_) => { Ok(_) => {
list_store.remove(&list_store.get_iter(&tree_path).unwrap()); list_store.remove(&list_store.get_iter(tree_path).unwrap());
} }
Err(_) => messages += format!("Failed to remove folder {}/{} because folder doesn't exists, you don't have permissions or isn't empty.\n", path, name).as_str(), Err(_) => messages += format!("Failed to remove folder {}/{} because folder doesn't exists, you don't have permissions or isn't empty.\n", path, name).as_str(),
} }
@ -640,12 +640,12 @@ fn main() {
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data // Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
for tree_path in selection_rows.iter().rev() { for tree_path in selection_rows.iter().rev() {
let name = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsEmptyFiles::Name as i32).get::<String>().unwrap().unwrap(); let name = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsEmptyFiles::Name as i32).get::<String>().unwrap().unwrap();
let path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsEmptyFiles::Path as i32).get::<String>().unwrap().unwrap(); let path = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsEmptyFiles::Path as i32).get::<String>().unwrap().unwrap();
match fs::remove_file(format!("{}/{}", path, name)) { match fs::remove_file(format!("{}/{}", path, name)) {
Ok(_) => { Ok(_) => {
list_store.remove(&list_store.get_iter(&tree_path).unwrap()); list_store.remove(&list_store.get_iter(tree_path).unwrap());
} }
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(), Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
} }
@ -667,12 +667,12 @@ fn main() {
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data // Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
for tree_path in selection_rows.iter().rev() { for tree_path in selection_rows.iter().rev() {
let name = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsTemporaryFiles::Name as i32).get::<String>().unwrap().unwrap(); let name = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsTemporaryFiles::Name as i32).get::<String>().unwrap().unwrap();
let path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsTemporaryFiles::Path as i32).get::<String>().unwrap().unwrap(); let path = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsTemporaryFiles::Path as i32).get::<String>().unwrap().unwrap();
match fs::remove_file(format!("{}/{}", path, name)) { match fs::remove_file(format!("{}/{}", path, name)) {
Ok(_) => { Ok(_) => {
list_store.remove(&list_store.get_iter(&tree_path).unwrap()); list_store.remove(&list_store.get_iter(tree_path).unwrap());
} }
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(), Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
} }
@ -694,12 +694,12 @@ fn main() {
// Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data // Must be deleted from end to start, because when deleting entries, TreePath(and also TreeIter) will points to invalid data
for tree_path in selection_rows.iter().rev() { for tree_path in selection_rows.iter().rev() {
let name = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsBigFiles::Name as i32).get::<String>().unwrap().unwrap(); let name = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsBigFiles::Name as i32).get::<String>().unwrap().unwrap();
let path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsBigFiles::Path as i32).get::<String>().unwrap().unwrap(); let path = tree_model.get_value(&tree_model.get_iter(tree_path).unwrap(), ColumnsBigFiles::Path as i32).get::<String>().unwrap().unwrap();
match fs::remove_file(format!("{}/{}", path, name)) { match fs::remove_file(format!("{}/{}", path, name)) {
Ok(_) => { Ok(_) => {
list_store.remove(&list_store.get_iter(&tree_path).unwrap()); list_store.remove(&list_store.get_iter(tree_path).unwrap());
} }
Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(), Err(_) => messages += format!("Failed to remove file {}/{} because file doesn't exists or you don't have permissions.\n", path, name).as_str(),
} }
@ -1343,7 +1343,7 @@ fn main() {
} }
} }
print_text_messages_to_text_view(&text_messages, &text_view_errors); print_text_messages_to_text_view(text_messages, &text_view_errors);
} }
// Set state // Set state
@ -1395,7 +1395,7 @@ fn main() {
let values: [&dyn ToValue; 3] = [&(name[index + 1..].to_string()), &(name[..index].to_string()), &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())]; let values: [&dyn ToValue; 3] = [&(name[index + 1..].to_string()), &(name[..index].to_string()), &(NaiveDateTime::from_timestamp(entry.modified_date as i64, 0).to_string())];
list_store.set(&list_store.append(), &col_indices, &values); list_store.set(&list_store.append(), &col_indices, &values);
} }
print_text_messages_to_text_view(&text_messages, &text_view_errors); print_text_messages_to_text_view(text_messages, &text_view_errors);
} }
// Set state // Set state
@ -1445,7 +1445,7 @@ fn main() {
let values: [&dyn ToValue; 3] = [&(name[index + 1..].to_string()), &(name[..index].to_string()), &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())]; let values: [&dyn ToValue; 3] = [&(name[index + 1..].to_string()), &(name[..index].to_string()), &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())];
list_store.set(&list_store.append(), &col_indices, &values); list_store.set(&list_store.append(), &col_indices, &values);
} }
print_text_messages_to_text_view(&text_messages, &text_view_errors); print_text_messages_to_text_view(text_messages, &text_view_errors);
} }
// Set state // Set state
@ -1502,7 +1502,7 @@ fn main() {
list_store.set(&list_store.append(), &col_indices, &values); list_store.set(&list_store.append(), &col_indices, &values);
} }
} }
print_text_messages_to_text_view(&text_messages, &text_view_errors); print_text_messages_to_text_view(text_messages, &text_view_errors);
} }
// Set state // Set state
@ -1552,7 +1552,7 @@ fn main() {
let values: [&dyn ToValue; 3] = [&(name[index + 1..].to_string()), &(name[..index].to_string()), &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())]; let values: [&dyn ToValue; 3] = [&(name[index + 1..].to_string()), &(name[..index].to_string()), &(NaiveDateTime::from_timestamp(file_entry.modified_date as i64, 0).to_string())];
list_store.set(&list_store.append(), &col_indices, &values); list_store.set(&list_store.append(), &col_indices, &values);
} }
print_text_messages_to_text_view(&text_messages, &text_view_errors); print_text_messages_to_text_view(text_messages, &text_view_errors);
} }
// Set state // Set state