diff --git a/crates/ui-egui/src/dialogs/package.rs b/crates/ui-egui/src/dialogs/package.rs index 2ff2097975..25d17d3902 100644 --- a/crates/ui-egui/src/dialogs/package.rs +++ b/crates/ui-egui/src/dialogs/package.rs @@ -151,13 +151,14 @@ fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result { let start = move |app: &mut VectorcraftApp| background::run(app, enabled, label, None, work, move |app, r| packaged(app, r, web, in_background.get())); // Both in the background: the package, collected from the document as it is now, starts once - // the save is written. + // the save is written, with the automation roots in force at OK. if let Some(id) = saving.filter(|_| enabled) { later.set(true); app.ui.dialog = None; + let scope = vectorcraft_engine::file_access::ScopeHandle::capture(); background::after(app, id, move |app, r| { if saved(r) - && let Err(e) = start(app) + && let Err(e) = scope.run(|| start(app)) { app.status(e); } diff --git a/crates/ui-egui/src/dialogs/tests_package.rs b/crates/ui-egui/src/dialogs/tests_package.rs index 5c9e899354..acd1368ed4 100644 --- a/crates/ui-egui/src/dialogs/tests_package.rs +++ b/crates/ui-egui/src/dialogs/tests_package.rs @@ -248,6 +248,35 @@ fn a_failed_save_before_packaging_writes_no_package() { } } +/// A package that an automation request confined to its roots asks for, started once the +/// document's background save is written, is still confined to those roots, though the save's +/// result arrives outside the request. +#[test] +fn a_package_started_after_its_save_keeps_the_automation_roots() { + let (dir, elsewhere) = (Folder::new("scope"), Folder::new("scope-elsewhere")); + let (doc, out) = (dir.path("card.vectorcraft"), elsewhere.path("out")); + let root = std::path::Path::new(&out).join("card Folder"); + let mut app = saved(&dir); + let files = Files::default(); + let recorded = files.clone(); + app.services.write_shared = Some(Arc::new(move |p: &str, b: &[u8]| { + vectorcraft_engine::file_access::check_write(p)?; + recorded.lock().unwrap().push((p.to_string(), b.to_vec())); + Ok(()) + })); + let roots = AutomationRoots::new(&[dir.0.as_path()], &[dir.0.as_path()]).unwrap(); + app.run("shape.rectangle", json!({"x": 0, "y": 0, "width": 10, "height": 10})).unwrap(); + package_dialog(&mut app, &out); + let r = vectorcraft_engine::file_access::confine(roots.as_ref(), || confirm(&mut app)).unwrap(); + assert_eq!(r["background"], true, "{r}"); + // The save's result is applied outside the request, as the next frame does. + background::wait_all(&mut app); + assert_eq!(written(&files), [doc], "only the save, inside the roots"); + assert!(!root.exists(), "no package folder outside the roots"); + assert!(!app.session.active().unwrap().is_dirty(), "the save was written"); + assert!(app.ui.status.contains("failed"), "the package was refused: {}", app.ui.status); +} + #[test] fn a_package_made_at_once_waits_for_one_in_the_background() { let dir = Folder::new("twice");