diff --git a/crates/engine/src/cmd/lut_profiles.rs b/crates/engine/src/cmd/lut_profiles.rs index f03809b62..b7a0d4992 100644 --- a/crates/engine/src/cmd/lut_profiles.rs +++ b/crates/engine/src/cmd/lut_profiles.rs @@ -17,7 +17,7 @@ pub struct LutProfile { pub id: String, pub name: String, pub group: String, - /// The `.cube` file (the library's copy when there is a library on disk). + /// The library's copy of the `.cube` file (empty without a library on disk). pub file: String, } @@ -123,12 +123,9 @@ fn import(s: &mut Session, p: &Value) -> Result { std::fs::write(&f, &text).map_err(|e| bad(C, format!("{}: {e}", f.display())))?; f.to_string_lossy().to_string() } - None => { - // no library on disk: remember the original (the in-memory session ends with the app) - let f = std::env::temp_dir().join(format!("lightcraft-{}.cube", id.trim_start_matches("lut:"))); - std::fs::write(&f, &text).map_err(|e| bad(C, e.to_string()))?; - f.to_string_lossy().to_string() - } + // no library on disk: the registered LUT is all this session needs (a copy would only + // be read back when a library opens, and that takes its own list from its prefs) + None => String::new(), }; lightcraft_pipeline::lut::register(&id, lut); s.lut_profiles.push(LutProfile { id: id.clone(), name: display.clone(), group: group.clone(), file }); diff --git a/crates/engine/src/tests_import.rs b/crates/engine/src/tests_import.rs index 3d6469deb..f00ecc557 100644 --- a/crates/engine/src/tests_import.rs +++ b/crates/engine/src/tests_import.rs @@ -611,6 +611,34 @@ fn cube_luts_become_profiles() { /// Folder rename / move on disk: files and sidecars go along, the photos are relinked and /// still render; clashes and moving into itself are refused. +/// Without a library on disk an imported LUT lives only in this session: no copy of it is +/// left in the temp folder (#1952). +#[test] +fn cube_import_without_a_library_leaves_no_temp_copy() { + let src = temp_dir("cubemem"); + let mut cube = String::from("TITLE \"Temp Copy Check\"\nLUT_3D_SIZE 2\n"); + for b in 0..2 { + for g in 0..2 { + for r in 0..2 { + cube.push_str(&format!("{r} {g} {b}\n")); + } + } + } + std::fs::write(src.join("mem.cube"), &cube).unwrap(); + let leak = std::env::temp_dir().join("lightcraft-imported-temp-copy-check.cube"); + let _ = std::fs::remove_file(&leak); + let mut s = Session::new().with_fs(); + let r = s.execute("profile.import", &json!({"paths": [src.join("mem.cube").to_string_lossy()]})).unwrap(); + let id = r["imported"][0]["id"].as_str().unwrap().to_string(); + assert!(lightcraft_pipeline::lut::get(&id).is_some(), "usable in this session"); + let file = s.lut_profiles.iter().find(|p| p.id == id).unwrap().file.clone(); + assert!(file.is_empty() || Path::new(&file).starts_with(&src), "no copy written: {file}"); + drop(s); + assert!(!leak.exists(), "{} left behind", leak.display()); + lightcraft_pipeline::lut::unregister(&id); + let _ = std::fs::remove_dir_all(&src); +} + #[test] fn folders_rename_and_move_with_their_photos() { let root = temp_dir("folders");