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:
parent
196411c101
commit
085da0369e
|
@ -19,6 +19,7 @@ pub struct FileEntry {
|
|||
}
|
||||
|
||||
/// Info struck with helpful information's about results
|
||||
#[derive(Default)]
|
||||
pub struct Info {
|
||||
pub number_of_checked_files: usize,
|
||||
pub number_of_checked_folders: usize,
|
||||
|
@ -27,22 +28,10 @@ pub struct Info {
|
|||
pub taken_space: u64,
|
||||
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 {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
impl Info {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,8 +48,8 @@ pub struct BigFile {
|
|||
}
|
||||
|
||||
impl BigFile {
|
||||
pub fn new() -> BigFile {
|
||||
BigFile {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
text_messages: Default::default(),
|
||||
information: Info::new(),
|
||||
big_files: Default::default(),
|
||||
|
@ -78,15 +67,15 @@ impl BigFile {
|
|||
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
|
||||
}
|
||||
|
||||
pub fn get_text_messages(&self) -> &Messages {
|
||||
pub const fn get_text_messages(&self) -> &Messages {
|
||||
&self.text_messages
|
||||
}
|
||||
|
||||
pub fn get_information(&self) -> &Info {
|
||||
pub const fn get_information(&self) -> &Info {
|
||||
&self.information
|
||||
}
|
||||
|
||||
|
@ -121,7 +110,7 @@ impl BigFile {
|
|||
continue;
|
||||
} // Permissions denied
|
||||
};
|
||||
for entry in read_dir {
|
||||
'dir: for entry in read_dir {
|
||||
let entry_data = match entry {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
|
@ -147,7 +136,6 @@ impl BigFile {
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut is_excluded_dir = false;
|
||||
next_folder = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
|
@ -158,25 +146,16 @@ impl BigFile {
|
|||
|
||||
for ed in &self.directories.excluded_directories {
|
||||
if next_folder == *ed {
|
||||
is_excluded_dir = true;
|
||||
break;
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
if !is_excluded_dir {
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
found_expression = true;
|
||||
break;
|
||||
}
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
continue 'dir;
|
||||
}
|
||||
if found_expression {
|
||||
break;
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
} else if metadata.is_file() {
|
||||
let mut have_valid_extension: bool;
|
||||
let file_name_lowercase: String = match entry_data.file_name().into_string() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
|
@ -184,65 +163,50 @@ impl BigFile {
|
|||
.to_lowercase();
|
||||
|
||||
// Checking allowed extensions
|
||||
if !self.allowed_extensions.file_extensions.is_empty() {
|
||||
have_valid_extension = false;
|
||||
for extension in &self.allowed_extensions.file_extensions {
|
||||
if file_name_lowercase.ends_with((".".to_string() + extension.to_lowercase().as_str()).as_str()) {
|
||||
have_valid_extension = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
have_valid_extension = true;
|
||||
let allowed = self.allowed_extensions.file_extensions.iter().any(|e| file_name_lowercase.ends_with((".".to_string() + e.to_lowercase().as_str()).as_str()));
|
||||
if !allowed {
|
||||
// Not an allowed extension, ignore it.
|
||||
self.information.number_of_ignored_files += 1;
|
||||
continue 'dir;
|
||||
}
|
||||
|
||||
// Checking files
|
||||
if have_valid_extension {
|
||||
let current_file_name = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
// Checking expressions
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, ¤t_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
|
||||
},
|
||||
let current_file_name = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
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 {
|
||||
self.information.number_of_ignored_files += 1;
|
||||
// Checking expressions
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, ¤t_file_name) {
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// Probably this is symbolic links so we are free to ignore this
|
||||
self.information.number_of_ignored_things += 1;
|
||||
|
|
|
@ -7,9 +7,10 @@ use std::time::SystemTime;
|
|||
pub struct Common();
|
||||
impl Common {
|
||||
/// 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)]
|
||||
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> {
|
||||
|
|
|
@ -3,16 +3,14 @@ use crate::common_messages::Messages;
|
|||
use std::path::Path;
|
||||
use std::time::SystemTime;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Directories {
|
||||
pub excluded_directories: Vec<String>,
|
||||
pub included_directories: Vec<String>,
|
||||
}
|
||||
impl Directories {
|
||||
pub fn new() -> Directories {
|
||||
Directories {
|
||||
excluded_directories: vec![],
|
||||
included_directories: vec![],
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Setting included directories, at least one must be provided
|
||||
|
@ -244,9 +242,3 @@ impl Directories {
|
|||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Directories {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ use crate::common::Common;
|
|||
use crate::common_messages::Messages;
|
||||
use std::time::SystemTime;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Extensions {
|
||||
pub file_extensions: Vec<String>,
|
||||
}
|
||||
|
||||
impl Extensions {
|
||||
pub fn new() -> Extensions {
|
||||
Extensions { file_extensions: vec![] }
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
/// List of allowed extensions, only files with this extensions will be checking if are duplicates
|
||||
/// 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());
|
||||
}
|
||||
}
|
||||
impl Default for Extensions {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ use crate::common::Common;
|
|||
use crate::common_messages::Messages;
|
||||
use std::time::SystemTime;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ExcludedItems {
|
||||
pub items: Vec<String>,
|
||||
}
|
||||
|
||||
impl ExcludedItems {
|
||||
pub fn new() -> ExcludedItems {
|
||||
ExcludedItems { items: vec![] }
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
/// Setting excluded items which needs to contains * wildcard
|
||||
/// 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());
|
||||
}
|
||||
}
|
||||
impl Default for ExcludedItems {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#[derive(Default)]
|
||||
pub struct Messages {
|
||||
pub messages: Vec<String>,
|
||||
pub warnings: Vec<String>,
|
||||
|
@ -5,12 +6,8 @@ pub struct Messages {
|
|||
}
|
||||
|
||||
impl Messages {
|
||||
pub fn new() -> Messages {
|
||||
Messages {
|
||||
messages: vec![],
|
||||
warnings: vec![],
|
||||
errors: vec![],
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
pub fn print_messages(&self) {
|
||||
if !self.messages.is_empty() {
|
||||
|
@ -40,8 +37,3 @@ impl Messages {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl Default for Messages {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ pub struct FileEntry {
|
|||
}
|
||||
|
||||
/// Info struck with helpful information's about results
|
||||
#[derive(Default)]
|
||||
pub struct Info {
|
||||
pub number_of_checked_files: usize,
|
||||
pub number_of_checked_folders: usize,
|
||||
|
@ -55,30 +56,10 @@ pub struct Info {
|
|||
pub number_of_failed_to_remove_files: usize,
|
||||
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 {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
impl Info {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,8 +79,8 @@ pub struct DuplicateFinder {
|
|||
}
|
||||
|
||||
impl DuplicateFinder {
|
||||
pub fn new() -> DuplicateFinder {
|
||||
DuplicateFinder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
files_with_identical_size: Default::default(),
|
||||
|
@ -125,23 +106,23 @@ impl DuplicateFinder {
|
|||
self.debug_print();
|
||||
}
|
||||
|
||||
pub fn get_check_method(&self) -> &CheckingMethod {
|
||||
pub const fn get_check_method(&self) -> &CheckingMethod {
|
||||
&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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
pub fn get_text_messages(&self) -> &Messages {
|
||||
pub const fn get_text_messages(&self) -> &Messages {
|
||||
&self.text_messages
|
||||
}
|
||||
|
||||
pub fn get_information(&self) -> &Info {
|
||||
pub const fn get_information(&self) -> &Info {
|
||||
&self.information
|
||||
}
|
||||
|
||||
|
@ -207,7 +188,7 @@ impl DuplicateFinder {
|
|||
};
|
||||
|
||||
// Check every sub folder/file/link etc.
|
||||
for entry in read_dir {
|
||||
'dir: for entry in read_dir {
|
||||
let entry_data = match entry {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
|
@ -233,7 +214,6 @@ impl DuplicateFinder {
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut is_excluded_dir = false;
|
||||
next_folder = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
|
@ -244,25 +224,17 @@ impl DuplicateFinder {
|
|||
|
||||
for ed in &self.directories.excluded_directories {
|
||||
if next_folder == *ed {
|
||||
is_excluded_dir = true;
|
||||
break;
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
if !is_excluded_dir {
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
found_expression = true;
|
||||
break;
|
||||
}
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
continue 'dir;
|
||||
}
|
||||
if found_expression {
|
||||
break;
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
} 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() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
|
@ -270,20 +242,14 @@ impl DuplicateFinder {
|
|||
.to_lowercase();
|
||||
|
||||
// Checking allowed extensions
|
||||
if !self.allowed_extensions.file_extensions.is_empty() {
|
||||
have_valid_extension = false;
|
||||
for extension in &self.allowed_extensions.file_extensions {
|
||||
if file_name_lowercase.ends_with((".".to_string() + extension.to_lowercase().as_str()).as_str()) {
|
||||
have_valid_extension = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
have_valid_extension = true;
|
||||
let allowed = self.allowed_extensions.file_extensions.iter().any(|e| file_name_lowercase.ends_with((".".to_string() + e.to_lowercase().as_str()).as_str()));
|
||||
if !allowed {
|
||||
// Not an allowed extension, ignore it.
|
||||
self.information.number_of_ignored_files += 1;
|
||||
continue 'dir;
|
||||
}
|
||||
|
||||
// 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()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
|
@ -292,16 +258,11 @@ impl DuplicateFinder {
|
|||
};
|
||||
|
||||
// Checking expressions
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, ¤t_file_name) {
|
||||
found_expression = true;
|
||||
break;
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
if found_expression {
|
||||
break;
|
||||
}
|
||||
|
||||
// Creating new file entry
|
||||
let fe: FileEntry = FileEntry {
|
||||
|
@ -328,6 +289,7 @@ impl DuplicateFinder {
|
|||
|
||||
self.information.number_of_checked_files += 1;
|
||||
} else {
|
||||
// Probably this is symbolic links so we are free to ignore this
|
||||
self.information.number_of_ignored_files += 1;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,7 @@ pub struct FileEntry {
|
|||
}
|
||||
|
||||
/// Info struck with helpful information's about results
|
||||
#[derive(Default)]
|
||||
pub struct Info {
|
||||
pub number_of_checked_files: usize,
|
||||
pub number_of_checked_folders: usize,
|
||||
|
@ -33,22 +34,8 @@ pub struct Info {
|
|||
pub number_of_failed_to_remove_files: usize,
|
||||
}
|
||||
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_empty_files: 0,
|
||||
number_of_removed_files: 0,
|
||||
number_of_failed_to_remove_files: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Info {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,8 +52,8 @@ pub struct EmptyFiles {
|
|||
}
|
||||
|
||||
impl EmptyFiles {
|
||||
pub fn new() -> EmptyFiles {
|
||||
EmptyFiles {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
@ -86,15 +73,15 @@ impl EmptyFiles {
|
|||
self.debug_print();
|
||||
}
|
||||
|
||||
pub fn get_empty_files(&self) -> &Vec<FileEntry> {
|
||||
pub const fn get_empty_files(&self) -> &Vec<FileEntry> {
|
||||
&self.empty_files
|
||||
}
|
||||
|
||||
pub fn get_text_messages(&self) -> &Messages {
|
||||
pub const fn get_text_messages(&self) -> &Messages {
|
||||
&self.text_messages
|
||||
}
|
||||
|
||||
pub fn get_information(&self) -> &Info {
|
||||
pub const fn get_information(&self) -> &Info {
|
||||
&self.information
|
||||
}
|
||||
|
||||
|
@ -147,7 +134,7 @@ impl EmptyFiles {
|
|||
};
|
||||
|
||||
// Check every sub folder/file/link etc.
|
||||
for entry in read_dir {
|
||||
'dir: for entry in read_dir {
|
||||
let entry_data = match entry {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
|
@ -173,7 +160,6 @@ impl EmptyFiles {
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut is_excluded_dir = false;
|
||||
next_folder = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
|
@ -184,25 +170,16 @@ impl EmptyFiles {
|
|||
|
||||
for ed in &self.directories.excluded_directories {
|
||||
if next_folder == *ed {
|
||||
is_excluded_dir = true;
|
||||
break;
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
if !is_excluded_dir {
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
found_expression = true;
|
||||
break;
|
||||
}
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
continue 'dir;
|
||||
}
|
||||
if found_expression {
|
||||
break;
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
} else if metadata.is_file() {
|
||||
let mut have_valid_extension: bool;
|
||||
let file_name_lowercase: String = match entry_data.file_name().into_string() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
|
@ -210,20 +187,14 @@ impl EmptyFiles {
|
|||
.to_lowercase();
|
||||
|
||||
// Checking allowed extensions
|
||||
if !self.allowed_extensions.file_extensions.is_empty() {
|
||||
have_valid_extension = false;
|
||||
for extension in &self.allowed_extensions.file_extensions {
|
||||
if file_name_lowercase.ends_with((".".to_string() + extension.to_lowercase().as_str()).as_str()) {
|
||||
have_valid_extension = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
have_valid_extension = true;
|
||||
let allowed = self.allowed_extensions.file_extensions.iter().any(|e| file_name_lowercase.ends_with((".".to_string() + e.to_lowercase().as_str()).as_str()));
|
||||
if !allowed {
|
||||
// Not an allowed extension, ignore it.
|
||||
self.information.number_of_ignored_files += 1;
|
||||
continue 'dir;
|
||||
}
|
||||
|
||||
// Checking files
|
||||
if metadata.len() == 0 && have_valid_extension {
|
||||
if metadata.len() == 0 {
|
||||
let current_file_name = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
|
@ -232,16 +203,11 @@ impl EmptyFiles {
|
|||
};
|
||||
|
||||
// Checking expressions
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, ¤t_file_name) {
|
||||
found_expression = true;
|
||||
break;
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
if found_expression {
|
||||
break;
|
||||
}
|
||||
|
||||
// Creating new file entry
|
||||
let fe: FileEntry = FileEntry {
|
||||
|
|
|
@ -34,29 +34,22 @@ pub struct EmptyFolder {
|
|||
}
|
||||
|
||||
/// Info struck with helpful information's about results
|
||||
#[derive(Default)]
|
||||
pub struct Info {
|
||||
number_of_checked_folders: usize,
|
||||
pub number_of_empty_folders: usize,
|
||||
}
|
||||
impl Info {
|
||||
pub fn new() -> Info {
|
||||
Info {
|
||||
number_of_checked_folders: 0,
|
||||
number_of_empty_folders: 0,
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Info {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
/// Method implementation for EmptyFolder
|
||||
impl EmptyFolder {
|
||||
/// New function providing basics values
|
||||
pub fn new() -> EmptyFolder {
|
||||
EmptyFolder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
information: Default::default(),
|
||||
delete_folders: false,
|
||||
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
|
||||
}
|
||||
|
||||
pub fn get_text_messages(&self) -> &Messages {
|
||||
pub const fn get_text_messages(&self) -> &Messages {
|
||||
&self.text_messages
|
||||
}
|
||||
pub fn get_information(&self) -> &Info {
|
||||
pub const fn get_information(&self) -> &Info {
|
||||
&self.information
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ pub struct FileEntry {
|
|||
}
|
||||
|
||||
/// Info struck with helpful information's about results
|
||||
#[derive(Default)]
|
||||
pub struct Info {
|
||||
pub number_of_checked_files: usize,
|
||||
pub number_of_checked_folders: usize,
|
||||
|
@ -32,22 +33,8 @@ pub struct Info {
|
|||
pub number_of_failed_to_remove_files: usize,
|
||||
}
|
||||
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_temporary_files: 0,
|
||||
number_of_removed_files: 0,
|
||||
number_of_failed_to_remove_files: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Info {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,8 +50,8 @@ pub struct Temporary {
|
|||
}
|
||||
|
||||
impl Temporary {
|
||||
pub fn new() -> Temporary {
|
||||
Temporary {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
text_messages: Messages::new(),
|
||||
information: Info::new(),
|
||||
recursive_search: true,
|
||||
|
@ -83,14 +70,14 @@ impl Temporary {
|
|||
self.debug_print();
|
||||
}
|
||||
|
||||
pub fn get_temporary_files(&self) -> &Vec<FileEntry> {
|
||||
pub const fn get_temporary_files(&self) -> &Vec<FileEntry> {
|
||||
&self.temporary_files
|
||||
}
|
||||
pub fn get_text_messages(&self) -> &Messages {
|
||||
pub const fn get_text_messages(&self) -> &Messages {
|
||||
&self.text_messages
|
||||
}
|
||||
|
||||
pub fn get_information(&self) -> &Info {
|
||||
pub const fn get_information(&self) -> &Info {
|
||||
&self.information
|
||||
}
|
||||
|
||||
|
@ -139,7 +126,7 @@ impl Temporary {
|
|||
};
|
||||
|
||||
// Check every sub folder/file/link etc.
|
||||
for entry in read_dir {
|
||||
'dir: for entry in read_dir {
|
||||
let entry_data = match entry {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
|
@ -165,7 +152,6 @@ impl Temporary {
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut is_excluded_dir = false;
|
||||
next_folder = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
|
@ -176,88 +162,67 @@ impl Temporary {
|
|||
|
||||
for ed in &self.directories.excluded_directories {
|
||||
if next_folder == *ed {
|
||||
is_excluded_dir = true;
|
||||
break;
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
if !is_excluded_dir {
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
found_expression = true;
|
||||
break;
|
||||
}
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, &next_folder) {
|
||||
continue 'dir;
|
||||
}
|
||||
if found_expression {
|
||||
break;
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
}
|
||||
folders_to_check.push(next_folder);
|
||||
} else if metadata.is_file() {
|
||||
let file_name_lowercase: String = match entry_data.file_name().into_string() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
}
|
||||
.to_lowercase();
|
||||
let mut is_temporary_file: bool = false;
|
||||
|
||||
// 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"];
|
||||
|
||||
if file_name_lowercase.contains('.') {
|
||||
for temp in temporary_with_dot.iter() {
|
||||
if file_name_lowercase.ends_with(temp) {
|
||||
is_temporary_file = true;
|
||||
}
|
||||
}
|
||||
if !file_name_lowercase.contains('.') || !temporary_with_dot.iter().any(|f| file_name_lowercase.ends_with(f)) {
|
||||
self.information.number_of_ignored_files += 1;
|
||||
continue 'dir;
|
||||
}
|
||||
|
||||
// Checking files
|
||||
if is_temporary_file {
|
||||
let current_file_name = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
// Checking expressions
|
||||
let mut found_expression: bool = false;
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, ¤t_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
|
||||
},
|
||||
let current_file_name = "".to_owned()
|
||||
+ ¤t_folder
|
||||
+ match &entry_data.file_name().into_string() {
|
||||
Ok(t) => t,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
// Adding files to Vector
|
||||
self.temporary_files.push(fe);
|
||||
|
||||
self.information.number_of_checked_files += 1;
|
||||
} else {
|
||||
self.information.number_of_ignored_files += 1;
|
||||
// Checking expressions
|
||||
for expression in &self.excluded_items.items {
|
||||
if Common::regex_check(expression, ¤t_file_name) {
|
||||
continue 'dir;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// Probably this is symbolic links so we are free to ignore this
|
||||
self.information.number_of_ignored_things += 1;
|
||||
|
|
|
@ -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
|
||||
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 path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsDuplicates::Path 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();
|
||||
|
||||
match fs::remove_file(format!("{}/{}", path, name)) {
|
||||
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(),
|
||||
}
|
||||
|
@ -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
|
||||
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 path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsEmptyFolders::Path 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();
|
||||
|
||||
match fs::remove_dir(format!("{}/{}", path, name)) {
|
||||
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(),
|
||||
}
|
||||
|
@ -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
|
||||
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 path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsEmptyFiles::Path 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();
|
||||
|
||||
match fs::remove_file(format!("{}/{}", path, name)) {
|
||||
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(),
|
||||
}
|
||||
|
@ -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
|
||||
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 path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsTemporaryFiles::Path 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();
|
||||
|
||||
match fs::remove_file(format!("{}/{}", path, name)) {
|
||||
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(),
|
||||
}
|
||||
|
@ -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
|
||||
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 path = tree_model.get_value(&tree_model.get_iter(&tree_path).unwrap(), ColumnsBigFiles::Path 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();
|
||||
|
||||
match fs::remove_file(format!("{}/{}", path, name)) {
|
||||
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(),
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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())];
|
||||
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
|
||||
|
@ -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())];
|
||||
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
|
||||
|
@ -1502,7 +1502,7 @@ fn main() {
|
|||
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
|
||||
|
@ -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())];
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue