Skip to content

Commit 47ee0d4

Browse files
committed
Meta
1 parent 5b183bf commit 47ee0d4

8 files changed

Lines changed: 140 additions & 33 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ resolver = "2"
2020
panic = "unwind"
2121

2222
# Should find more panics, that now are hidden from user - in long term it should decrease bugs in app
23-
# There is one big disadvantage - in case of overflow/underflow entire app crashes and panic cannot be catched and app aborts
23+
# There is one big disadvantage - in case of overflow/underflow entire app crashes and not everywhere I catch this panic so app aborts
2424
# So feel free to disable it, if you want
2525
overflow-checks = true
2626

czkawka_core/src/common_cache.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::collections::BTreeMap;
2+
use std::fs;
23
use std::io::{BufReader, BufWriter};
4+
use std::path::Path;
35

46
use fun_time::fun_time;
7+
use humansize::{BINARY, format_size};
58
use image::imageops::FilterType;
69
use image_hasher::HashAlg;
710
use log::{debug, error};
@@ -50,6 +53,10 @@ pub fn get_duplicate_cache_file(type_of_hash: &HashType, is_prehash: bool) -> St
5053
format!("cache_duplicates_{type_of_hash:?}{prehash_str}_{CACHE_DUPLICATE_VERSION}.bin")
5154
}
5255

56+
fn get_cache_size(file_name: &Path) -> String {
57+
fs::metadata(file_name).map_or_else(|_| "<unknown size>".to_string(), |metadata| format_size(metadata.len(), BINARY))
58+
}
59+
5360
#[fun_time(message = "save_cache_to_file_generalized", level = "debug")]
5461
pub fn save_cache_to_file_generalized<T>(cache_file_name: &str, hashmap: &BTreeMap<String, T>, save_also_as_json: bool, minimum_file_size: u64) -> Messages
5562
where
@@ -68,7 +75,7 @@ where
6875
debug!("Failed to save cache to file {cache_file:?}");
6976
return text_messages;
7077
}
71-
debug!("Saved binary to file {cache_file:?}");
78+
debug!("Saved cache to binary file {cache_file:?} with size {}", get_cache_size(&cache_file));
7279
}
7380
if save_also_as_json {
7481
if let Some(file_handler_json) = file_handler_json {
@@ -78,7 +85,7 @@ where
7885
debug!("Failed to save cache to file {cache_file_json:?}");
7986
return text_messages;
8087
}
81-
debug!("Saved json to file {cache_file_json:?}");
88+
debug!("Saved cache to json file {cache_file_json:?} with size {}", get_cache_size(&cache_file_json));
8289
}
8390
}
8491

@@ -197,8 +204,10 @@ where
197204
let mut text_messages = Messages::new();
198205

199206
if let Some(((file_handler, cache_file), (file_handler_json, cache_file_json))) = common::open_cache_folder(cache_file_name, false, true, &mut text_messages.warnings) {
207+
let cache_full_name;
200208
let mut vec_loaded_entries: Vec<T>;
201209
if let Some(file_handler) = file_handler {
210+
cache_full_name = cache_file.clone();
202211
let reader = BufReader::new(file_handler);
203212

204213
// TODO cannot use limits
@@ -217,6 +226,7 @@ where
217226
}
218227
};
219228
} else {
229+
cache_full_name = cache_file_json.clone();
220230
let reader = BufReader::new(file_handler_json.expect("This cannot fail, because if file_handler is None, then this cannot be None"));
221231
vec_loaded_entries = match serde_json::from_reader(reader) {
222232
Ok(t) => t,
@@ -265,7 +275,11 @@ where
265275

266276
text_messages.messages.push(format!("Properly loaded {} cache entries.", vec_loaded_entries.len()));
267277

268-
debug!("Loaded cache from file {cache_file_name} (or json alternative) - {} results", vec_loaded_entries.len());
278+
debug!(
279+
"Loaded cache from file {cache_file_name} (or json alternative) - {} results - size {}",
280+
vec_loaded_entries.len(),
281+
get_cache_size(&cache_full_name)
282+
);
269283
return (text_messages, Some(vec_loaded_entries));
270284
}
271285
debug!("Failed to load cache from file {cache_file_name} because not exists");

czkawka_core/src/tools/broken_files.rs

Lines changed: 101 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{fs, mem, panic};
88

99
use crossbeam_channel::Sender;
1010
use fun_time::fun_time;
11-
use log::debug;
11+
use log::{debug, error};
1212
use pdf::PdfError;
1313
use pdf::PdfError::Try;
1414
use pdf::file::FileOptions;
@@ -458,15 +458,15 @@ fn check_extension_availability(
458458
audio_extensions: &HashSet<&&'static str>,
459459
pdf_extensions: &HashSet<&&'static str>,
460460
) -> TypeOfFile {
461-
let Some(extension) = full_name.extension() else {
462-
debug_assert!(false, "Missing extension");
461+
let Some(file_name) = full_name.file_name() else {
462+
error!("Missing file name in file - \"{}\"", full_name.to_string_lossy());
463+
debug_assert!(false, "Missing file name in file - \"{}\"", full_name.to_string_lossy());
463464
return TypeOfFile::Unknown;
464465
};
466+
let Some(file_name_str) = file_name.to_str() else { return TypeOfFile::Unknown };
467+
let Some(extension_idx) = file_name_str.rfind('.') else { return TypeOfFile::Unknown };
468+
let extension_str = &file_name_str[extension_idx + 1..];
465469

466-
let Some(extension_str) = extension.to_str() else {
467-
debug_assert!(false, "Extension not really fully str");
468-
return TypeOfFile::Unknown;
469-
};
470470
let extension_lowercase = extension_str.to_ascii_lowercase();
471471

472472
if images_extensions.contains(&extension_lowercase.as_str()) {
@@ -478,8 +478,8 @@ fn check_extension_availability(
478478
} else if pdf_extensions.contains(&extension_lowercase.as_str()) {
479479
TypeOfFile::PDF
480480
} else {
481-
eprintln!("File with unknown extension: \"{}\" - {extension_lowercase}", full_name.to_string_lossy());
482-
debug_assert!(false, "File with unknown extension");
481+
error!("File with unknown extension: \"{}\" - {extension_lowercase}", full_name.to_string_lossy());
482+
debug_assert!(false, "File with unknown extension - \"{}\" - {extension_lowercase}", full_name.to_string_lossy());
483483
TypeOfFile::Unknown
484484
}
485485
}
@@ -520,3 +520,95 @@ impl CommonData for BrokenFiles {
520520
&mut self.common_data
521521
}
522522
}
523+
524+
#[cfg(test)]
525+
mod tests {
526+
use std::collections::HashSet;
527+
use std::path::Path;
528+
529+
use super::*;
530+
531+
#[test]
532+
fn test_check_extension_availability_image() {
533+
let images_extensions: HashSet<&&str> = ["jpg", "png", "gif"].iter().collect();
534+
let zip_extensions: HashSet<&&str> = HashSet::new();
535+
let audio_extensions: HashSet<&&str> = HashSet::new();
536+
let pdf_extensions: HashSet<&&str> = HashSet::new();
537+
538+
let path = Path::new("test.jpg");
539+
assert_eq!(
540+
check_extension_availability(path, &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions),
541+
TypeOfFile::Image
542+
);
543+
}
544+
545+
#[test]
546+
fn test_check_extension_availability_zip() {
547+
let images_extensions: HashSet<&&str> = HashSet::new();
548+
let zip_extensions: HashSet<&&str> = ["zip", "rar"].iter().collect();
549+
let audio_extensions: HashSet<&&str> = HashSet::new();
550+
let pdf_extensions: HashSet<&&str> = HashSet::new();
551+
552+
let path = Path::new("test.zip");
553+
assert_eq!(
554+
check_extension_availability(path, &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions),
555+
TypeOfFile::ArchiveZip
556+
);
557+
}
558+
559+
#[test]
560+
fn test_check_extension_availability_audio() {
561+
let images_extensions: HashSet<&&str> = HashSet::new();
562+
let zip_extensions: HashSet<&&str> = HashSet::new();
563+
let audio_extensions: HashSet<&&str> = ["mp3", "wav"].iter().collect();
564+
let pdf_extensions: HashSet<&&str> = HashSet::new();
565+
566+
let path = Path::new("test.mp3");
567+
assert_eq!(
568+
check_extension_availability(path, &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions),
569+
TypeOfFile::Audio
570+
);
571+
}
572+
573+
#[test]
574+
fn test_check_extension_availability_pdf() {
575+
let images_extensions: HashSet<&&str> = HashSet::new();
576+
let zip_extensions: HashSet<&&str> = HashSet::new();
577+
let audio_extensions: HashSet<&&str> = HashSet::new();
578+
let pdf_extensions: HashSet<&&str> = std::iter::once(&"pdf").collect();
579+
580+
let path = Path::new("test.pdf");
581+
assert_eq!(
582+
check_extension_availability(path, &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions),
583+
TypeOfFile::PDF
584+
);
585+
}
586+
587+
#[test]
588+
fn test_check_extension_availability_no_extension() {
589+
let images_extensions: HashSet<&&str> = HashSet::new();
590+
let zip_extensions: HashSet<&&str> = HashSet::new();
591+
let audio_extensions: HashSet<&&str> = HashSet::new();
592+
let pdf_extensions: HashSet<&&str> = HashSet::new();
593+
594+
let path = Path::new("test");
595+
assert_eq!(
596+
check_extension_availability(path, &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions),
597+
TypeOfFile::Unknown
598+
);
599+
}
600+
601+
#[test]
602+
fn test_check_no_extension() {
603+
let images_extensions: HashSet<&&str> = HashSet::new();
604+
let zip_extensions: HashSet<&&str> = HashSet::new();
605+
let audio_extensions: HashSet<&&str> = ["mp3", "wav"].iter().collect();
606+
let pdf_extensions: HashSet<&&str> = HashSet::new();
607+
608+
let path = Path::new("/home/.mp3");
609+
assert_eq!(
610+
check_extension_availability(path, &images_extensions, &zip_extensions, &audio_extensions, &pdf_extensions),
611+
TypeOfFile::Audio
612+
);
613+
}
614+
}

krokiet/src/connect_open.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
use crate::{Callabler, MainWindow};
21
use czkawka_core::common::get_config_cache_path;
32
use log::error;
43
use slint::ComponentHandle;
54

5+
use crate::{Callabler, MainWindow};
6+
67
pub fn connect_open_items(app: &MainWindow) {
78
app.global::<Callabler>().on_item_opened(move |path| {
89
match open::that(&*path) {

krokiet/src/connect_rename.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ fn rename_selected_items(files_with_new_extensions: Vec<(String, String, String)
4242
let mut errors = vec![];
4343
for (folder, file_name, new_extension) in files_with_new_extensions {
4444
let file_stem = Path::new(&file_name).file_stem().map(|e| e.to_string_lossy().to_string()).unwrap_or_default();
45-
let new_full_path = format!("{}{}{}.{}", folder, MAIN_SEPARATOR, file_stem, new_extension);
46-
let old_full_path = format!("{}{}{}", folder, MAIN_SEPARATOR, file_name);
45+
let new_full_path = format!("{folder}{MAIN_SEPARATOR}{file_stem}.{new_extension}");
46+
let old_full_path = format!("{folder}{MAIN_SEPARATOR}{file_name}");
4747
if let Err(e) = fs::rename(&old_full_path, &new_full_path) {
48-
errors.push(format!("Failed to rename file {} to {} with error {}", old_full_path, new_full_path, e));
48+
errors.push(format!("Failed to rename file {old_full_path} to {new_full_path} with error {e}"));
4949
}
5050
}
5151
errors

krokiet/src/connect_select.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ pub fn connect_select(app: &MainWindow) {
1515
let current_model = get_tool_model(&app, active_tab);
1616

1717
let new_model = match select_mode {
18-
SelectMode::SelectAll => select_all(current_model),
19-
SelectMode::UnselectAll => deselect_all(current_model),
20-
SelectMode::InvertSelection => invert_selection(current_model),
21-
SelectMode::SelectTheBiggestSize => select_by_size_date(current_model, active_tab, true, true),
22-
SelectMode::SelectTheSmallestSize => select_by_size_date(current_model, active_tab, false, true),
23-
SelectMode::SelectTheBiggestResolution => select_by_resolution(current_model, active_tab, true),
24-
SelectMode::SelectTheSmallestResolution => select_by_resolution(current_model, active_tab, false),
25-
SelectMode::SelectNewest => select_by_size_date(current_model, active_tab, true, false),
26-
SelectMode::SelectOldest => select_by_size_date(current_model, active_tab, false, false),
18+
SelectMode::SelectAll => select_all(&current_model),
19+
SelectMode::UnselectAll => deselect_all(&current_model),
20+
SelectMode::InvertSelection => invert_selection(&current_model),
21+
SelectMode::SelectTheBiggestSize => select_by_size_date(&current_model, active_tab, true, true),
22+
SelectMode::SelectTheSmallestSize => select_by_size_date(&current_model, active_tab, false, true),
23+
SelectMode::SelectTheBiggestResolution => select_by_resolution(&current_model, active_tab, true),
24+
SelectMode::SelectTheSmallestResolution => select_by_resolution(&current_model, active_tab, false),
25+
SelectMode::SelectNewest => select_by_size_date(&current_model, active_tab, true, false),
26+
SelectMode::SelectOldest => select_by_size_date(&current_model, active_tab, false, false),
2727
};
2828
set_tool_model(&app, active_tab, new_model);
2929
});
@@ -96,7 +96,7 @@ fn translate_select_mode(select_mode: SelectMode) -> String {
9696
}
9797

9898
// TODO, when model will be able to contain i64 instead two i32, this function could be merged with select_by_size_date
99-
fn select_by_resolution(model: ModelRc<MainListModel>, active_tab: CurrentTab, biggest: bool) -> ModelRc<MainListModel> {
99+
fn select_by_resolution(model: &ModelRc<MainListModel>, active_tab: CurrentTab, biggest: bool) -> ModelRc<MainListModel> {
100100
let is_header_mode = get_is_header_mode(active_tab);
101101
assert!(is_header_mode); // non header modes not really have reason to use this function
102102

@@ -140,7 +140,7 @@ fn select_by_resolution(model: ModelRc<MainListModel>, active_tab: CurrentTab, b
140140
ModelRc::new(VecModel::from(old_data))
141141
}
142142

143-
fn select_by_size_date(model: ModelRc<MainListModel>, active_tab: CurrentTab, biggest_newest: bool, size: bool) -> ModelRc<MainListModel> {
143+
fn select_by_size_date(model: &ModelRc<MainListModel>, active_tab: CurrentTab, biggest_newest: bool, size: bool) -> ModelRc<MainListModel> {
144144
let is_header_mode = get_is_header_mode(active_tab);
145145
assert!(is_header_mode); // non header modes not really have reason to use this function
146146

@@ -187,7 +187,7 @@ fn select_by_size_date(model: ModelRc<MainListModel>, active_tab: CurrentTab, bi
187187
ModelRc::new(VecModel::from(old_data))
188188
}
189189

190-
fn select_all(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
190+
fn select_all(model: &ModelRc<MainListModel>) -> ModelRc<MainListModel> {
191191
let mut old_data = model.iter().collect::<Vec<_>>();
192192
for x in &mut old_data {
193193
if !x.header_row {
@@ -197,13 +197,13 @@ fn select_all(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
197197
ModelRc::new(VecModel::from(old_data))
198198
}
199199

200-
fn deselect_all(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
200+
fn deselect_all(model: &ModelRc<MainListModel>) -> ModelRc<MainListModel> {
201201
let mut old_data = model.iter().collect::<Vec<_>>();
202202
old_data.iter_mut().for_each(|x| x.checked = false);
203203
ModelRc::new(VecModel::from(old_data))
204204
}
205205

206-
fn invert_selection(model: ModelRc<MainListModel>) -> ModelRc<MainListModel> {
206+
fn invert_selection(model: &ModelRc<MainListModel>) -> ModelRc<MainListModel> {
207207
let mut old_data = model.iter().collect::<Vec<_>>();
208208
for x in &mut old_data {
209209
if !x.header_row {

krokiet/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
// Remove console window in Windows OS
22
#![windows_subsystem = "windows"]
33
#![allow(unknown_lints)] // May be disabled, but locally I use nightly clippy
4-
#![allow(clippy::comparison_chain)]
54
#![allow(clippy::collapsible_if)]
65
#![allow(clippy::collapsible_else_if)]
7-
#![allow(clippy::should_panic_without_expect)]
6+
// #![warn(clippy::unwrap_used)] // Cannot use due unwrap used in a lot of places
87

98
use std::rc::Rc;
109
use std::sync::Arc;

krokiet/src/settings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ pub fn load_settings_from_file(app: &MainWindow) {
302302

303303
// Validate here values and set "proper"
304304
// preset_names should have 10 items
305+
#[allow(clippy::comparison_chain)]
305306
if base_settings.preset_names.len() > 10 {
306307
base_settings.preset_names.truncate(10);
307308
} else if base_settings.preset_names.len() < 10 {

0 commit comments

Comments
 (0)