Split functions in big file finder
This commit is contained in:
parent
7b1600bdaa
commit
31d8d937b1
|
@ -1,7 +1,7 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fs::{File, Metadata};
|
use std::fs::{DirEntry, File, Metadata};
|
||||||
use std::io::{BufWriter, Write};
|
use std::io::{BufWriter, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU64};
|
use std::sync::atomic::{AtomicBool, AtomicU64};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -232,82 +232,9 @@ impl BigFile {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if metadata.is_dir() {
|
if metadata.is_dir() {
|
||||||
if !self.recursive_search {
|
self.check_folder_children(&mut dir_result, &mut warnings, current_folder, &entry_data);
|
||||||
continue 'dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
let next_folder = current_folder.join(entry_data.file_name());
|
|
||||||
if self.directories.is_excluded(&next_folder) {
|
|
||||||
continue 'dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.excluded_items.is_excluded(&next_folder) {
|
|
||||||
continue 'dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
if self.directories.exclude_other_filesystems() {
|
|
||||||
match self.directories.is_on_other_filesystems(&next_folder) {
|
|
||||||
Ok(true) => continue 'dir,
|
|
||||||
Err(e) => warnings.push(e.to_string()),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dir_result.push(next_folder);
|
|
||||||
} else if metadata.is_file() {
|
} else if metadata.is_file() {
|
||||||
atomic_file_counter.fetch_add(1, Ordering::Relaxed);
|
self.collect_file_entry(&atomic_file_counter, &metadata, &entry_data, &mut fe_result, &mut warnings, current_folder);
|
||||||
|
|
||||||
if metadata.len() == 0 {
|
|
||||||
continue 'dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
let file_name_lowercase: String = match entry_data.file_name().into_string() {
|
|
||||||
Ok(t) => t,
|
|
||||||
Err(_inspected) => {
|
|
||||||
warnings.push(flc!(
|
|
||||||
"core_file_not_utf8_name",
|
|
||||||
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
|
|
||||||
));
|
|
||||||
continue 'dir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.to_lowercase();
|
|
||||||
|
|
||||||
if !self.allowed_extensions.matches_filename(&file_name_lowercase) {
|
|
||||||
continue 'dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_file_name = current_folder.join(entry_data.file_name());
|
|
||||||
if self.excluded_items.is_excluded(¤t_file_name) {
|
|
||||||
continue 'dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(_inspected) => {
|
|
||||||
warnings.push(flc!(
|
|
||||||
"core_file_modified_before_epoch",
|
|
||||||
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
|
|
||||||
));
|
|
||||||
0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
warnings.push(flc!(
|
|
||||||
"core_file_no_modification_date",
|
|
||||||
generate_translation_hashmap(vec![("name", current_file_name.display().to_string()), ("reason", e.to_string())])
|
|
||||||
));
|
|
||||||
0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
fe_result.push((fe.size, fe));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(dir_result, warnings, fe_result)
|
(dir_result, warnings, fe_result)
|
||||||
|
@ -331,8 +258,102 @@ impl BigFile {
|
||||||
progress_thread_run.store(false, Ordering::Relaxed);
|
progress_thread_run.store(false, Ordering::Relaxed);
|
||||||
progress_thread_handle.join().unwrap();
|
progress_thread_handle.join().unwrap();
|
||||||
|
|
||||||
// Extract n biggest files to new TreeMap
|
self.extract_n_biggest_files(old_map);
|
||||||
|
|
||||||
|
Common::print_time(start_time, SystemTime::now(), "look_for_big_files");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_folder_children(&self, dir_result: &mut Vec<PathBuf>, warnings: &mut Vec<String>, current_folder: &Path, entry_data: &DirEntry) {
|
||||||
|
if !self.recursive_search {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_folder = current_folder.join(entry_data.file_name());
|
||||||
|
if self.directories.is_excluded(&next_folder) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.excluded_items.is_excluded(&next_folder) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
if self.directories.exclude_other_filesystems() {
|
||||||
|
match self.directories.is_on_other_filesystems(&next_folder) {
|
||||||
|
Ok(true) => return,
|
||||||
|
Err(e) => warnings.push(e),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dir_result.push(next_folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collect_file_entry(
|
||||||
|
&self,
|
||||||
|
atomic_file_counter: &Arc<AtomicU64>,
|
||||||
|
metadata: &Metadata,
|
||||||
|
entry_data: &DirEntry,
|
||||||
|
fe_result: &mut Vec<(u64, FileEntry)>,
|
||||||
|
warnings: &mut Vec<String>,
|
||||||
|
current_folder: &Path,
|
||||||
|
) {
|
||||||
|
atomic_file_counter.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
if metadata.len() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_name_lowercase: String = match entry_data.file_name().into_string() {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(_inspected) => {
|
||||||
|
warnings.push(flc!(
|
||||||
|
"core_file_not_utf8_name",
|
||||||
|
generate_translation_hashmap(vec![("name", entry_data.path().display().to_string())])
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.to_lowercase();
|
||||||
|
|
||||||
|
if !self.allowed_extensions.matches_filename(&file_name_lowercase) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_file_name = current_folder.join(entry_data.file_name());
|
||||||
|
if self.excluded_items.is_excluded(¤t_file_name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(_inspected) => {
|
||||||
|
warnings.push(flc!(
|
||||||
|
"core_file_modified_before_epoch",
|
||||||
|
generate_translation_hashmap(vec![("name", current_file_name.display().to_string())])
|
||||||
|
));
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
warnings.push(flc!(
|
||||||
|
"core_file_no_modification_date",
|
||||||
|
generate_translation_hashmap(vec![("name", current_file_name.display().to_string()), ("reason", e.to_string())])
|
||||||
|
));
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
fe_result.push((fe.size, fe));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_n_biggest_files(&mut self, old_map: BTreeMap<u64, Vec<FileEntry>>) {
|
||||||
let iter: Box<dyn Iterator<Item = _>>;
|
let iter: Box<dyn Iterator<Item = _>>;
|
||||||
if self.search_mode == SearchMode::SmallestFiles {
|
if self.search_mode == SearchMode::SmallestFiles {
|
||||||
iter = Box::new(old_map.into_iter());
|
iter = Box::new(old_map.into_iter());
|
||||||
|
@ -360,9 +381,6 @@ impl BigFile {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::print_time(start_time, SystemTime::now(), "look_for_big_files");
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_number_of_files_to_check(&mut self, number_of_files_to_check: usize) {
|
pub fn set_number_of_files_to_check(&mut self, number_of_files_to_check: usize) {
|
||||||
|
|
|
@ -30,6 +30,12 @@ pub enum DeleteMethod {
|
||||||
Delete,
|
Delete,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug, Copy)]
|
||||||
|
pub enum AudioCheckMethod {
|
||||||
|
Tags,
|
||||||
|
Content,
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||||
pub struct MusicSimilarity : u32 {
|
pub struct MusicSimilarity : u32 {
|
||||||
|
@ -112,6 +118,7 @@ pub struct SameMusic {
|
||||||
delete_outdated_cache: bool, // TODO add this to GUI
|
delete_outdated_cache: bool, // TODO add this to GUI
|
||||||
use_reference_folders: bool,
|
use_reference_folders: bool,
|
||||||
save_also_as_json: bool,
|
save_also_as_json: bool,
|
||||||
|
check_type: AudioCheckMethod,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SameMusic {
|
impl SameMusic {
|
||||||
|
@ -138,6 +145,7 @@ impl SameMusic {
|
||||||
use_reference_folders: false,
|
use_reference_folders: false,
|
||||||
duplicated_music_entries_referenced: vec![],
|
duplicated_music_entries_referenced: vec![],
|
||||||
save_also_as_json: false,
|
save_also_as_json: false,
|
||||||
|
check_type: AudioCheckMethod::Content,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,13 +156,20 @@ impl SameMusic {
|
||||||
self.stopped_search = true;
|
self.stopped_search = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !self.check_records_multithreaded(stop_receiver, progress_sender) {
|
match self.check_type {
|
||||||
self.stopped_search = true;
|
AudioCheckMethod::Tags => {
|
||||||
return;
|
if !self.read_tags(stop_receiver, progress_sender) {
|
||||||
}
|
self.stopped_search = true;
|
||||||
if !self.check_for_duplicates(stop_receiver, progress_sender) {
|
return;
|
||||||
self.stopped_search = true;
|
}
|
||||||
return;
|
if !self.check_for_duplicate_tags(stop_receiver, progress_sender) {
|
||||||
|
self.stopped_search = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AudioCheckMethod::Content => {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.delete_files();
|
self.delete_files();
|
||||||
self.debug_print();
|
self.debug_print();
|
||||||
|
@ -308,7 +323,7 @@ impl SameMusic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_records_multithreaded(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
fn read_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||||
let start_time: SystemTime = SystemTime::now();
|
let start_time: SystemTime = SystemTime::now();
|
||||||
|
|
||||||
let loaded_hash_map;
|
let loaded_hash_map;
|
||||||
|
@ -504,11 +519,11 @@ impl SameMusic {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::print_time(start_time, SystemTime::now(), "check_records_multithreaded");
|
Common::print_time(start_time, SystemTime::now(), "read_tags");
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
fn check_for_duplicates(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
fn check_for_duplicate_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender<ProgressData>>) -> bool {
|
||||||
assert!(MusicSimilarity::NONE != self.music_similarity, "This can't be none");
|
assert!(MusicSimilarity::NONE != self.music_similarity, "This can't be none");
|
||||||
let start_time: SystemTime = SystemTime::now();
|
let start_time: SystemTime = SystemTime::now();
|
||||||
|
|
||||||
|
@ -748,7 +763,7 @@ impl SameMusic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::print_time(start_time, SystemTime::now(), "check_for_duplicates");
|
Common::print_time(start_time, SystemTime::now(), "check_for_duplicate_tags");
|
||||||
|
|
||||||
// Clear unused data
|
// Clear unused data
|
||||||
self.music_entries.clear();
|
self.music_entries.clear();
|
||||||
|
|
|
@ -160,7 +160,7 @@
|
||||||
(5,122,"GtkCheckButton","check_button_music_genre",117,None,None,None,4),
|
(5,122,"GtkCheckButton","check_button_music_genre",117,None,None,None,4),
|
||||||
(5,123,"GtkCheckButton","check_button_music_length",117,None,None,None,5),
|
(5,123,"GtkCheckButton","check_button_music_length",117,None,None,None,5),
|
||||||
(5,124,"GtkBox",None,116,None,None,None,1),
|
(5,124,"GtkBox",None,116,None,None,None,1),
|
||||||
(5,125,"GtkCheckButton","check_button_music_approximate_comparison",124,None,None,None,None),
|
(5,125,"GtkCheckButton","check_button_music_approximate_comparison",124,None,None,None,2),
|
||||||
(5,126,"GtkScrolledWindow","scrolled_window_same_music_finder",116,None,None,None,2),
|
(5,126,"GtkScrolledWindow","scrolled_window_same_music_finder",116,None,None,None,2),
|
||||||
(5,127,"GtkLabel",None,115,None,None,None,None),
|
(5,127,"GtkLabel",None,115,None,None,None,None),
|
||||||
(5,128,"GtkNotebookPage",None,56,None,None,None,8),
|
(5,128,"GtkNotebookPage",None,56,None,None,None,8),
|
||||||
|
@ -235,6 +235,8 @@
|
||||||
(5,230,"GtkBox",None,229,None,None,None,None),
|
(5,230,"GtkBox",None,229,None,None,None,None),
|
||||||
(5,231,"GtkImage",None,230,None,None,None,None),
|
(5,231,"GtkImage",None,230,None,None,None,None),
|
||||||
(5,232,"GtkLabel","label_buttons_sort",230,None,None,None,1),
|
(5,232,"GtkLabel","label_buttons_sort",230,None,None,None,1),
|
||||||
|
(5,234,"GtkLabel","label_audio_check_type",124,None,None,None,None),
|
||||||
|
(5,235,"GtkComboBoxText","combo_box_audio_check_type",124,None,None,None,1),
|
||||||
(6,1,"GtkPopover","popover_right_click",None,None,None,None,None),
|
(6,1,"GtkPopover","popover_right_click",None,None,None,None,None),
|
||||||
(6,2,"GtkBox",None,1,None,None,None,None),
|
(6,2,"GtkBox",None,1,None,None,None,None),
|
||||||
(6,3,"GtkButton","buttons_popover_right_click_open_file",2,None,None,None,None),
|
(6,3,"GtkButton","buttons_popover_right_click_open_file",2,None,None,None,None),
|
||||||
|
@ -765,6 +767,8 @@
|
||||||
(5,230,"GtkWidget","halign","center",None,None,None,None,None),
|
(5,230,"GtkWidget","halign","center",None,None,None,None,None),
|
||||||
(5,231,"GtkImage","icon-name","image-missing",None,None,None,None,None),
|
(5,231,"GtkImage","icon-name","image-missing",None,None,None,None,None),
|
||||||
(5,232,"GtkLabel","label","SortMenu",None,None,None,None,None),
|
(5,232,"GtkLabel","label","SortMenu",None,None,None,None,None),
|
||||||
|
(5,234,"GtkLabel","label","Audio check type",None,None,None,None,None),
|
||||||
|
(5,234,"GtkWidget","margin-end","2",None,None,None,None,None),
|
||||||
(6,1,"GtkPopover","child",None,None,None,None,None,2),
|
(6,1,"GtkPopover","child",None,None,None,None,None,2),
|
||||||
(6,1,"GtkPopover","position","left",None,None,None,None,None),
|
(6,1,"GtkPopover","position","left",None,None,None,None,None),
|
||||||
(6,2,"GtkOrientable","orientation","vertical",None,None,None,None,None),
|
(6,2,"GtkOrientable","orientation","vertical",None,None,None,None,None),
|
||||||
|
|
|
@ -728,6 +728,15 @@
|
||||||
<property name="margin-bottom">2</property>
|
<property name="margin-bottom">2</property>
|
||||||
<property name="margin-end">5</property>
|
<property name="margin-end">5</property>
|
||||||
<property name="margin-start">5</property>
|
<property name="margin-start">5</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label_audio_check_type">
|
||||||
|
<property name="label">Audio check type</property>
|
||||||
|
<property name="margin-end">2</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBoxText" id="combo_box_audio_check_type"/>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkCheckButton" id="check_button_music_approximate_comparison">
|
<object class="GtkCheckButton" id="check_button_music_approximate_comparison">
|
||||||
<property name="focusable">1</property>
|
<property name="focusable">1</property>
|
||||||
|
|
Loading…
Reference in a new issue