diff --git a/crates/engine/src/lens_profiles.rs b/crates/engine/src/lens_profiles.rs index afcb0ab399..c52d49f392 100644 --- a/crates/engine/src/lens_profiles.rs +++ b/crates/engine/src/lens_profiles.rs @@ -90,7 +90,7 @@ pub fn database() -> Option> { } let generation = generation(); // the app's own folder without its marker is a download that never finished: not read (the start fetches it) - let db = if downloaded && !crate::lensfun_download::complete(&dir) { None } else { load(&dir) }; + let db = if downloaded && !crate::lensfun_download::complete(&dir) { None } else { load(&dir, downloaded) }; let mut loaded = LOADED.write().unwrap_or_else(PoisonError::into_inner); // a reload while the files were read: they may be the old ones, so they aren't kept (the next call reads again) if GENERATION.load(Ordering::Relaxed) == generation { @@ -99,8 +99,10 @@ pub fn database() -> Option> { db } -fn load(dir: &Path) -> Option> { +fn load(dir: &Path, downloaded: bool) -> Option> { + let whose = if downloaded { "downloaded" } else { ENV }; if !dir.is_dir() { + log::warn!("lens database: {} ({whose}) is missing or not a folder", dir.display()); return None; } match LensDb::load_dir(dir) { @@ -108,6 +110,8 @@ fn load(dir: &Path) -> Option> { for (file, e) in errors { log::warn!("lens database: skipped {file}: {e}"); } + let (level, line) = summary(dir, whose, &db); + log::log!(level, "{line}"); (!db.lenses.is_empty()).then(|| Arc::new(db)) } Err(e) => { @@ -117,6 +121,17 @@ fn load(dir: &Path) -> Option> { } } +/// The log line for a database read from `dir`: where it is and how many lenses and cameras it has, so a user +/// setting up `LIGHTCRAFT_LENSFUN_DIR` can see whether it was found; a folder without lenses is a warning. +fn summary(dir: &Path, whose: &str, db: &LensDb) -> (log::Level, String) { + let (lenses, cameras) = (db.lenses.len(), db.cameras.len()); + if lenses == 0 { + (log::Level::Warn, format!("lens database: no lenses in {} ({whose}); lens profiles are not applied", dir.display())) + } else { + (log::Level::Info, format!("lens database: read {} ({whose}): lenses {lenses}, cameras {cameras}", dir.display())) + } +} + /// The database's name for the lens a photo's file calls `lens` (taken with `camera`, the make and model as the /// library shows them): "Canon EF 70-200mm f/2.8L IS II USM". `None` without a database or a match. pub fn profile_name(db: &LensDb, camera: &str, lens: &str) -> Option { @@ -193,6 +208,18 @@ mod tests { } } + /// The log says where the database was read from and what it holds, and warns when it holds no lenses (#2511). + #[test] + fn the_log_names_the_folder_and_what_it_holds() { + let dir = Path::new("/lensfun/db"); + let (level, line) = summary(dir, ENV, &LensDb::parse(DB).unwrap()); + assert_eq!(level, log::Level::Info); + assert!(line.contains("lenses 1, cameras 1") && line.contains("/lensfun/db") && line.contains(ENV), "{line}"); + let (level, line) = summary(dir, "downloaded", &LensDb::parse("").unwrap()); + assert_eq!(level, log::Level::Warn); + assert!(line.contains("no lenses") && line.contains("downloaded"), "{line}"); + } + #[test] fn exif_lens_is_found_and_converted() { let db = LensDb::parse(DB).unwrap(); diff --git a/docs/lens-profiles.md b/docs/lens-profiles.md index c49ee6ad42..e55b38ff4c 100644 --- a/docs/lens-profiles.md +++ b/docs/lens-profiles.md @@ -50,6 +50,8 @@ Sync carry Enable Lens Corrections and its amounts, and each photo keeps the pro (`crates/engine/src/tests/lens_refresh.rs`). Files are read once per folder and again after a download. Invalid files are skipped with a warning in the log. +Each read logs the folder, whether it is the download or `LIGHTCRAFT_LENSFUN_DIR`, and how many lenses and cameras +it holds; a folder that is missing or holds no lenses is logged as a warning (#2511). ## What is applied