Bind delete

pull/1087/head
Rafał Mikrut 8 months ago
parent e50d930683
commit f91abb966b

@ -132,15 +132,8 @@ pub struct DuplicatesArgs {
long_help = "Methods to search files.\nNAME - Fast but but rarely usable,\nSIZE - Fast but not accurate, checking by the file's size,\nHASH - The slowest method, checking by the hash of the entire file"
)]
pub search_method: CheckingMethod,
#[clap(
short = 'D',
long,
default_value = "NONE",
value_parser = parse_delete_method,
help = "Delete method (AEN, AEO, ON, OO, HARD)",
long_help = "Methods to delete the files.\nAEN - All files except the newest,\nAEO - All files except the oldest,\nON - Only 1 file, the newest,\nOO - Only 1 file, the oldest\nHARD - create hard link\nNONE - not delete files"
)]
pub delete_method: DeleteMethod,
#[clap(flatten)]
pub delete_method: DMethod,
#[clap(
short = 't',
long,
@ -165,7 +158,7 @@ pub struct DuplicatesArgs {
#[clap(flatten)]
pub allow_hard_links: AllowHardLinks,
#[clap(flatten)]
pub dryrun: DryRun,
pub dry_run: DryRun,
}
#[derive(Debug, clap::Args)]
@ -314,6 +307,10 @@ pub struct SimilarImagesArgs {
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
pub delete_method: DMethod,
#[clap(flatten)]
pub dry_run: DryRun,
#[clap(flatten)]
pub json_compact_file_to_save: JsonCompactFileToSave,
#[clap(flatten)]
pub json_pretty_file_to_save: JsonPrettyFileToSave,
@ -358,8 +355,10 @@ pub struct SameMusicArgs {
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
// #[clap(short = 'D', long, help = "Delete found files")]
// delete_files: bool, TODO
#[clap(flatten)]
pub delete_method: DMethod,
#[clap(flatten)]
pub dry_run: DryRun,
#[clap(
short = 'z',
long,
@ -464,8 +463,10 @@ pub struct SimilarVideosArgs {
pub excluded_directories: ExcludedDirectories,
#[clap(flatten)]
pub excluded_items: ExcludedItems,
// #[clap(short = 'D', long, help = "Delete found files")]
// delete_files: bool, TODO
#[clap(flatten)]
pub delete_method: DMethod,
#[clap(flatten)]
pub dry_run: DryRun,
#[clap(flatten)]
pub file_to_save: FileToSave,
#[clap(flatten)]
@ -533,6 +534,19 @@ pub struct BadExtensionsArgs {
pub exclude_other_filesystems: ExcludeOtherFilesystems,
}
#[derive(Debug, clap::Args)]
pub struct DMethod {
#[clap(
short = 'D',
long,
default_value = "NONE",
value_parser = parse_delete_method,
help = "Delete method (AEN, AEO, ON, OO, HARD)",
long_help = "Methods to delete the files.\nAEN - All files except the newest,\nAEO - All files except the oldest,\nON - Only 1 file, the newest,\nOO - Only 1 file, the oldest\nHARD - create hard link\nNONE - not delete files"
)]
pub delete_method: DeleteMethod,
}
#[derive(Debug, clap::Args)]
pub struct Directories {
#[clap(
@ -630,7 +644,7 @@ pub struct CaseSensitiveNameComparison {
#[derive(Debug, clap::Args)]
pub struct DryRun {
#[clap(long, help = "Do nothing and print the operation that would happen.")]
pub dryrun: bool,
pub dry_run: bool,
}
impl FileToSave {

@ -75,7 +75,7 @@ fn duplicates(duplicates: DuplicatesArgs) {
#[cfg(target_family = "unix")]
exclude_other_filesystems,
allow_hard_links,
dryrun,
dry_run,
case_sensitive_name_comparison,
} = duplicates;
@ -91,13 +91,13 @@ fn duplicates(duplicates: DuplicatesArgs) {
item.set_minimal_cache_file_size(minimal_cached_file_size);
item.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
item.set_check_method(search_method);
item.set_delete_method(delete_method);
item.set_delete_method(delete_method.delete_method);
item.set_hash_type(hash_type);
item.set_recursive_search(!not_recursive.not_recursive);
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.set_ignore_hard_links(!allow_hard_links.allow_hard_links);
item.set_dryrun(dryrun.dryrun);
item.set_dry_run(dry_run.dry_run);
item.set_case_sensitive_name_comparison(case_sensitive_name_comparison.case_sensitive_name_comparison);
item.find_duplicates(None, None);
@ -131,7 +131,9 @@ fn empty_folders(empty_folders: EmptyFoldersArgs) {
item.set_included_directory(directories.directories);
item.set_excluded_directory(excluded_directories.excluded_directories);
item.set_excluded_items(excluded_items.excluded_items);
item.set_delete_folder(delete_folders);
if delete_folders {
item.set_delete_method(DeleteMethod::Delete);
}
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
@ -292,6 +294,8 @@ fn similar_images(similar_images: SimilarImagesArgs) {
hash_alg,
image_filter,
hash_size,
delete_method,
dry_run,
} = similar_images;
set_number_of_threads(thread_number.thread_number);
@ -309,6 +313,8 @@ fn similar_images(similar_images: SimilarImagesArgs) {
item.set_image_filter(image_filter);
item.set_hash_alg(hash_alg);
item.set_hash_size(hash_size);
item.set_delete_method(delete_method.delete_method);
item.set_dry_run(dry_run.dry_run);
item.set_similarity(return_similarity_from_similarity_preset(&similarity_preset, hash_size));
@ -328,7 +334,7 @@ fn same_music(same_music: SameMusicArgs) {
directories,
excluded_directories,
excluded_items,
// delete_files,
delete_method,
file_to_save,
json_compact_file_to_save,
json_pretty_file_to_save,
@ -338,6 +344,7 @@ fn same_music(same_music: SameMusicArgs) {
minimal_file_size,
maximal_file_size,
music_similarity,
dry_run,
} = same_music;
set_number_of_threads(thread_number.thread_number);
@ -353,10 +360,8 @@ fn same_music(same_music: SameMusicArgs) {
#[cfg(target_family = "unix")]
item.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
item.set_music_similarity(music_similarity);
// if delete_files {
// // TODO item.set_delete_method(same_music::DeleteMethod::Delete);
// }
item.set_delete_method(delete_method.delete_method);
item.set_dry_run(dry_run.dry_run);
item.find_same_music(None, None);
@ -467,6 +472,8 @@ fn similar_videos(similar_videos: SimilarVideosArgs) {
minimal_file_size,
maximal_file_size,
allowed_extensions,
delete_method,
dry_run,
} = similar_videos;
set_number_of_threads(thread_number.thread_number);
@ -483,6 +490,8 @@ fn similar_videos(similar_videos: SimilarVideosArgs) {
item.set_minimal_file_size(minimal_file_size);
item.set_maximal_file_size(maximal_file_size);
item.set_tolerance(tolerance);
item.set_delete_method(delete_method.delete_method);
item.set_dry_run(dry_run.dry_run);
item.find_similar_videos(None, None);

@ -25,7 +25,10 @@ use log::{info, LevelFilter, Record};
use crate::common_dir_traversal::{CheckingMethod, ProgressData, ToolType};
use crate::common_directory::Directories;
use crate::common_items::ExcludedItems;
use crate::common_messages::Messages;
use crate::common_tool::DeleteMethod;
use crate::common_traits::ResultEntry;
use crate::duplicate::make_hard_link;
use crate::CZKAWKA_VERSION;
static NUMBER_OF_THREADS: state::InitCell<usize> = state::InitCell::new();
@ -234,35 +237,6 @@ pub fn create_crash_message(library_name: &str, file_path: &str, home_library_ur
}
impl Common {
pub fn delete_multiple_entries(entries: &[String]) -> Vec<String> {
let mut path: &Path;
let mut warnings: Vec<String> = Vec::new();
for entry in entries {
path = Path::new(entry);
if path.is_dir() {
if let Err(e) = fs::remove_dir_all(entry) {
warnings.push(format!("Failed to remove folder {entry}, reason {e}"));
}
} else if let Err(e) = fs::remove_file(entry) {
warnings.push(format!("Failed to remove file {entry}, reason {e}"));
}
}
warnings
}
pub fn delete_one_entry(entry: &str) -> String {
let path: &Path = Path::new(entry);
let mut warning: String = String::new();
if path.is_dir() {
if let Err(e) = fs::remove_dir_all(entry) {
warning = format!("Failed to remove folder {entry}, reason {e}");
}
} else if let Err(e) = fs::remove_file(entry) {
warning = format!("Failed to remove file {entry}, reason {e}");
}
warning
}
pub fn regex_check(expression: &str, directory: impl AsRef<Path>) -> bool {
if expression == "*" {
return true;
@ -374,6 +348,98 @@ pub fn check_folder_children(
dir_result.push(next_folder);
}
// Here we assume, that internal Vec<> have at least 1 object
#[allow(clippy::ptr_arg)]
pub fn delete_files_custom<T>(items: &Vec<&Vec<T>>, delete_method: &DeleteMethod, text_messages: &mut Messages, dry_run: bool) -> (u64, usize, usize)
where
T: ResultEntry + Clone,
{
let res = items
.iter()
.map(|values| {
let mut gained_space: u64 = 0;
let mut removed_files: usize = 0;
let mut failed_to_remove_files: usize = 0;
let mut infos = Vec::new();
let mut errors = Vec::new();
let mut all_values = (*values).clone();
let len = all_values.len();
// Sorted from oldest to newest - from smallest value to bigger
all_values.sort_unstable_by_key(ResultEntry::get_modified_date);
if delete_method == &DeleteMethod::HardLink {
let original_file = &all_values[0];
for file_entry in &all_values[1..] {
if dry_run {
infos.push(format!(
"dry_run - would create hardlink from {:?} to {:?}",
original_file.get_path(),
original_file.get_path()
));
} else {
if dry_run {
infos.push(format!("Replace file {:?} with hard link to {:?}", original_file.get_path(), file_entry.get_path()));
} else {
if let Err(e) = make_hard_link(original_file.get_path(), file_entry.get_path()) {
errors.push(format!(
"Cannot create hard link from {:?} to {:?} - {}",
file_entry.get_path(),
original_file.get_path(),
e
));
failed_to_remove_files += 1;
} else {
gained_space += 1;
removed_files += 1;
}
}
}
}
return (infos, errors, gained_space, removed_files, failed_to_remove_files);
}
let items = match delete_method {
DeleteMethod::Delete => &all_values,
DeleteMethod::AllExceptNewest => &all_values[..(len - 1)],
DeleteMethod::AllExceptOldest => &all_values[1..],
DeleteMethod::OneOldest => &all_values[..1],
DeleteMethod::OneNewest => &all_values[(len - 1)..],
DeleteMethod::HardLink | DeleteMethod::None => unreachable!("HardLink and None should be handled before"),
};
for i in items {
if dry_run {
infos.push(format!("dry_run - would delete file: {:?}", i.get_path()));
} else {
if let Err(e) = std::fs::remove_file(i.get_path()) {
errors.push(format!("Cannot delete file: {:?} - {e}", i.get_path()));
failed_to_remove_files += 1;
} else {
removed_files += 1;
gained_space += i.get_size();
}
}
}
(infos, errors, gained_space, removed_files, failed_to_remove_files)
})
.collect::<Vec<_>>();
let mut gained_space = 0;
let mut removed_files = 0;
let mut failed_to_remove_files = 0;
for (infos, errors, gained_space_v, removed_files_v, failed_to_remove_files_v) in res {
text_messages.messages.extend(infos);
text_messages.errors.extend(errors);
gained_space += gained_space_v;
removed_files += removed_files_v;
failed_to_remove_files += failed_to_remove_files_v;
}
(gained_space, removed_files, failed_to_remove_files)
}
pub fn filter_reference_folders_generic<T>(entries_to_check: Vec<Vec<T>>, directories: &Directories) -> Vec<(T, Vec<T>)>
where
T: ResultEntry,

@ -22,6 +22,7 @@ pub struct CommonToolData {
pub(crate) delete_outdated_cache: bool,
pub(crate) save_also_as_json: bool,
pub(crate) use_reference_folders: bool,
pub(crate) dry_run: bool,
}
#[derive(Eq, PartialEq, Clone, Debug, Copy, Default)]
@ -53,6 +54,7 @@ impl CommonToolData {
delete_outdated_cache: true,
save_also_as_json: false,
use_reference_folders: false,
dry_run: false,
}
}
}
@ -61,6 +63,13 @@ pub trait CommonData {
fn get_cd(&self) -> &CommonToolData;
fn get_cd_mut(&mut self) -> &mut CommonToolData;
fn set_dry_run(&mut self, dry_run: bool) {
self.get_cd_mut().dry_run = dry_run;
}
fn get_dry_run(&self) -> bool {
self.get_cd().dry_run
}
fn set_use_cache(&mut self, use_cache: bool) {
self.get_cd_mut().use_cache = use_cache;
}
@ -189,6 +198,8 @@ pub trait CommonData {
println!("Delete outdated cache: {:?}", self.get_cd().delete_outdated_cache);
println!("Save also as json: {:?}", self.get_cd().save_also_as_json);
println!("Delete method: {:?}", self.get_cd().delete_method);
println!("Use reference folders: {:?}", self.get_cd().use_reference_folders);
println!("Dry run: {:?}", self.get_cd().dry_run);
println!("---------------DEBUG PRINT MESSAGES---------------");
println!("Errors size - {}", self.get_cd().text_messages.errors.len());

@ -1,5 +1,4 @@
use std::collections::HashMap;
use std::collections::{BTreeMap, HashSet};
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt::Debug;
use std::fs::File;
use std::hash::Hasher;
@ -19,10 +18,9 @@ use log::debug;
use rayon::prelude::*;
use xxhash_rust::xxh3::Xxh3;
use crate::common::{prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
use crate::common::{delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
use crate::common_cache::{get_duplicate_cache_file, load_cache_from_file_generalized_by_size, save_cache_to_file_generalized};
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType};
use crate::common_messages::Messages;
use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
use crate::common_traits::*;
@ -82,7 +80,6 @@ pub struct DuplicateFinder {
check_method: CheckingMethod,
hash_type: HashType,
ignore_hard_links: bool,
dryrun: bool,
use_prehash_cache: bool,
minimal_cache_file_size: u64,
minimal_prehash_cache_file_size: u64,
@ -105,7 +102,6 @@ impl DuplicateFinder {
check_method: CheckingMethod::None,
ignore_hard_links: true,
hash_type: HashType::Blake3,
dryrun: false,
use_prehash_cache: true,
minimal_cache_file_size: 1024 * 256, // By default cache only >= 256 KB files
minimal_prehash_cache_file_size: 0,
@ -823,115 +819,26 @@ impl DuplicateFinder {
match self.check_method {
CheckingMethod::Name => {
let vec_files = self.files_with_identical_names.values().collect::<Vec<_>>();
delete_files(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.dryrun);
delete_files_custom(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run);
}
CheckingMethod::SizeName => {
let vec_files = self.files_with_identical_size_names.values().collect::<Vec<_>>();
delete_files(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.dryrun);
delete_files_custom(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run);
}
CheckingMethod::Hash => {
for vec_files in self.files_with_identical_hashes.values() {
let vev: Vec<&Vec<FileEntry>> = vec_files.iter().collect::<Vec<_>>();
delete_files(&vev, &self.common_data.delete_method, &mut self.common_data.text_messages, self.dryrun);
delete_files_custom(&vev, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run);
}
}
CheckingMethod::Size => {
let vec_files = self.files_with_identical_size.values().collect::<Vec<_>>();
delete_files(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.dryrun);
delete_files_custom(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run);
}
_ => panic!(),
}
}
}
// Here we assume, that internal Vec<> have at least 1 object
#[allow(clippy::ptr_arg)]
fn delete_files(items: &Vec<&Vec<FileEntry>>, delete_method: &DeleteMethod, text_messages: &mut Messages, dryrun: bool) -> (u64, usize, usize) {
let res = items
.iter()
.map(|values| {
let mut gained_space: u64 = 0;
let mut removed_files: usize = 0;
let mut failed_to_remove_files: usize = 0;
let mut infos = Vec::new();
let mut errors = Vec::new();
let mut all_values = (*values).clone();
let len = all_values.len();
// Sorted from oldest to newest - from smallest value to bigger
all_values.sort_unstable_by_key(ResultEntry::get_modified_date);
if delete_method == &DeleteMethod::HardLink {
let original_file = &all_values[0];
for file_entry in &all_values[1..] {
if dryrun {
infos.push(format!(
"Dryrun - would create hardlink from {:?} to {:?}",
original_file.get_path(),
original_file.get_path()
));
} else {
if dryrun {
infos.push(format!("Replace file {:?} with hard link to {:?}", original_file.get_path(), file_entry.get_path()));
} else {
if let Err(e) = make_hard_link(original_file.get_path(), file_entry.get_path()) {
errors.push(format!(
"Cannot create hard link from {:?} to {:?} - {}",
file_entry.get_path(),
original_file.get_path(),
e
));
failed_to_remove_files += 1;
} else {
gained_space += 1;
removed_files += 1;
}
}
}
}
return (infos, errors, gained_space, removed_files, failed_to_remove_files);
}
let items = match delete_method {
DeleteMethod::Delete => &all_values,
DeleteMethod::AllExceptNewest => &all_values[..(len - 1)],
DeleteMethod::AllExceptOldest => &all_values[1..],
DeleteMethod::OneOldest => &all_values[..1],
DeleteMethod::OneNewest => &all_values[(len - 1)..],
DeleteMethod::HardLink | DeleteMethod::None => unreachable!("HardLink and None should be handled before"),
};
for i in items {
if dryrun {
infos.push(format!("Dryrun - would delete file: {:?}", i.get_path()));
} else {
if let Err(e) = std::fs::remove_file(i.get_path()) {
errors.push(format!("Cannot delete file: {:?} - {e}", i.get_path()));
failed_to_remove_files += 1;
} else {
removed_files += 1;
gained_space += i.get_size();
}
}
}
(infos, errors, gained_space, removed_files, failed_to_remove_files)
})
.collect::<Vec<_>>();
let mut gained_space = 0;
let mut removed_files = 0;
let mut failed_to_remove_files = 0;
for (infos, errors, gained_space_v, removed_files_v, failed_to_remove_files_v) in res {
text_messages.messages.extend(infos);
text_messages.errors.extend(errors);
gained_space += gained_space_v;
removed_files += removed_files_v;
failed_to_remove_files += failed_to_remove_files_v;
}
(gained_space, removed_files, failed_to_remove_files)
}
impl DuplicateFinder {
pub fn set_case_sensitive_name_comparison(&mut self, case_sensitive_name_comparison: bool) {
@ -982,8 +889,8 @@ impl DuplicateFinder {
self.ignore_hard_links = ignore_hard_links;
}
pub fn set_dryrun(&mut self, dryrun: bool) {
self.dryrun = dryrun;
pub fn set_dry_run(&mut self, dry_run: bool) {
self.common_data.dry_run = dry_run;
}
pub fn set_check_method(&mut self, check_method: CheckingMethod) {

@ -1,5 +1,5 @@
use std::collections::BTreeMap;
use std::fs;
use std::{fs, mem};
use std::io::Write;
use std::path::PathBuf;
@ -8,15 +8,15 @@ use crossbeam_channel::Receiver;
use fun_time::fun_time;
use futures::channel::mpsc::UnboundedSender;
use log::debug;
use rayon::prelude::*;
use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, FolderEmptiness, FolderEntry, ProgressData, ToolType};
use crate::common_tool::{CommonData, CommonToolData};
use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
use crate::common_traits::{DebugPrint, PrintResults};
pub struct EmptyFolder {
common_data: CommonToolData,
information: Info,
delete_folders: bool,
empty_folder_list: BTreeMap<PathBuf, FolderEntry>, // Path, FolderEntry
}
@ -30,7 +30,6 @@ impl EmptyFolder {
Self {
common_data: CommonToolData::new(ToolType::EmptyFolders),
information: Default::default(),
delete_folders: false,
empty_folder_list: Default::default(),
}
}
@ -51,24 +50,23 @@ impl EmptyFolder {
return;
}
self.optimize_folders();
if self.delete_folders {
self.delete_empty_folders();
}
self.delete_files();
self.debug_print();
}
fn optimize_folders(&mut self) {
let mut new_directory_folders: BTreeMap<PathBuf, FolderEntry> = Default::default();
for (name, folder_entry) in &self.empty_folder_list {
for (name, folder_entry) in mem::take(&mut self.empty_folder_list) {
match &folder_entry.parent_path {
Some(t) => {
if !self.empty_folder_list.contains_key(t) {
new_directory_folders.insert(name.clone(), folder_entry.clone());
new_directory_folders.insert(name, folder_entry);
}
}
None => {
new_directory_folders.insert(name.clone(), folder_entry.clone());
new_directory_folders.insert(name, folder_entry);
}
}
}
@ -109,19 +107,24 @@ impl EmptyFolder {
}
}
#[fun_time(message = "delete_empty_folders")]
fn delete_empty_folders(&mut self) {
// Folders may be deleted or require too big privileges
for name in self.empty_folder_list.keys() {
match fs::remove_dir_all(name) {
Ok(()) => (),
Err(e) => self
.common_data
.text_messages
.warnings
.push(format!("Failed to remove folder {}, reason {}", name.display(), e)),
};
// #[fun_time(message = "delete_files")]
fn delete_files(&mut self) {
if self.get_delete_method() == DeleteMethod::None {
return;
}
let folders_to_remove = self.empty_folder_list.keys().collect::<Vec<_>>();
let errors: Vec<_> = folders_to_remove
.into_par_iter()
.filter_map(|name| {
if let Err(e) = fs::remove_dir_all(name) {
Some(format!("Failed to remove folder {name:?}, reason {e}"))
} else {
None
}
})
.collect();
self.get_text_messages_mut().errors.extend(errors);
}
}
@ -172,8 +175,3 @@ impl CommonData for EmptyFolder {
&mut self.common_data
}
}
impl EmptyFolder {
pub fn set_delete_folder(&mut self, delete_folder: bool) {
self.delete_folders = delete_folder;
}
}

@ -25,10 +25,12 @@ use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
use crate::common::{create_crash_message, filter_reference_folders_generic, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, AUDIO_FILES_EXTENSIONS};
use crate::common::{
create_crash_message, delete_files_custom, filter_reference_folders_generic, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, AUDIO_FILES_EXTENSIONS,
};
use crate::common_cache::{get_similar_music_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized};
use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ProgressData, ToolType};
use crate::common_tool::{CommonData, CommonToolData};
use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
use crate::common_traits::*;
bitflags! {
@ -653,20 +655,12 @@ impl SameMusic {
#[fun_time(message = "delete_files")]
fn delete_files(&mut self) {
if self.common_data.delete_method == DeleteMethod::None {
return;
}
// TODO
// match self.delete_method {
// DeleteMethod::Delete => {
// for file_entry in &self.music_entries {
// if fs::remove_file(file_entry.path.clone()).is_err() {
// self.common_data.text_messages.warnings.push(file_entry.path.display().to_string());
// }
// }
// }
// DeleteMethod::None => {
// //Just do nothing
// }
// }
let vec_files = self.duplicated_music_entries.iter().collect::<Vec<_>>();
delete_files_custom(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run);
}
}

@ -20,12 +20,12 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "heif")]
use crate::common::get_dynamic_image_from_heic;
use crate::common::{
check_folder_children, create_crash_message, get_dynamic_image_from_raw_image, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, HEIC_EXTENSIONS,
IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS,
check_folder_children, create_crash_message, delete_files_custom, get_dynamic_image_from_raw_image, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads,
HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS,
};
use crate::common_cache::{get_similar_images_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized};
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
use crate::common_tool::{CommonData, CommonToolData};
use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
use crate::common_traits::{DebugPrint, PrintResults, ResultEntry};
use crate::flc;
@ -140,6 +140,7 @@ impl SimilarImages {
self.common_data.stopped_search = true;
return;
}
self.delete_files();
self.debug_print();
}
@ -807,6 +808,15 @@ impl SimilarImages {
}
assert!(!found, "Found Invalid entries, verify errors before"); // TODO crashes with empty result with reference folder, verify why
}
fn delete_files(&mut self) {
if self.common_data.delete_method == DeleteMethod::None {
return;
}
let vec_files = self.similar_vectors.iter().collect::<Vec<_>>();
delete_files_custom(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run);
}
}
fn is_in_reference_folder(reference_directories: &[PathBuf], path: &Path) -> bool {

@ -15,10 +15,10 @@ use serde::{Deserialize, Serialize};
use vid_dup_finder_lib::HashCreationErrorKind::DetermineVideo;
use vid_dup_finder_lib::{NormalizedTolerance, VideoHash};
use crate::common::{check_folder_children, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, VIDEO_FILES_EXTENSIONS};
use crate::common::{check_folder_children, delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, VIDEO_FILES_EXTENSIONS};
use crate::common_cache::{get_similar_videos_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized};
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
use crate::common_tool::{CommonData, CommonToolData};
use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
use crate::common_traits::{DebugPrint, PrintResults, ResultEntry};
use crate::flc;
use crate::localizer_core::generate_translation_hashmap;
@ -123,6 +123,7 @@ impl SimilarVideos {
return;
}
}
self.delete_files();
self.debug_print();
}
@ -401,6 +402,15 @@ impl SimilarVideos {
.collect::<Vec<(FileEntry, Vec<FileEntry>)>>();
}
}
fn delete_files(&mut self) {
if self.common_data.delete_method == DeleteMethod::None {
return;
}
let vec_files = self.similar_vectors.iter().collect::<Vec<_>>();
delete_files_custom(&vec_files, &self.common_data.delete_method, &mut self.common_data.text_messages, self.common_data.dry_run);
}
}
impl Default for SimilarVideos {

Loading…
Cancel
Save