diff --git a/src/lib.rs b/src/lib.rs index 28bd9ce..15f9819 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,9 +40,21 @@ pub fn scan_images(root: &Path) -> Result> { if !entry.file_type().is_file() || !is_image_path(path) { continue; } - let bytes = fs::read(path)?; + let bytes = match fs::read(path) { + Ok(b) => b, + Err(e) => { + eprintln!("warning: skipping {}: {e}", path.display()); + continue; + } + }; let sha256 = format!("{:x}", Sha256::digest(&bytes)); - let img = image::open(path)?; + let img = match image::open(path) { + Ok(i) => i, + Err(e) => { + eprintln!("warning: skipping {}: {e}", path.display()); + continue; + } + }; let dhash = compute_dhash(&img); out.push(ImageEntry { path: path.to_path_buf(), diff --git a/tests/image_phase.rs b/tests/image_phase.rs index 2b3d0e3..28ba43b 100644 --- a/tests/image_phase.rs +++ b/tests/image_phase.rs @@ -109,6 +109,17 @@ fn single_image_no_duplicates() { assert!(groups.is_empty(), "single image should produce no duplicate groups"); } +#[test] +fn scan_skips_corrupt_image_files() { + // corrupt.png exists in fixtures dir with invalid PNG data + let dir = Path::new("/a0/usr/projects/deduper/.a0proj/test_media/images"); + let entries = scan_images(dir).expect("scan should not fail on corrupt files"); + // corrupt.png should be skipped, not cause an error + assert!(!entries.iter().any(|e| e.path.ends_with("corrupt.png")), "corrupt file should be skipped"); + // valid images still found + assert!(entries.iter().any(|e| e.path.ends_with("orig.jpg")), "valid images should still be found"); +} + #[test] fn cli_binary_reports_duplicates() { let bin = env!("CARGO_BIN_EXE_deduper");