diff --git a/crates/engine/src/cmd/plugin.rs b/crates/engine/src/cmd/plugin.rs index d583f6fe3..a5b71d538 100644 --- a/crates/engine/src/cmd/plugin.rs +++ b/crates/engine/src/cmd/plugin.rs @@ -846,6 +846,15 @@ pub(crate) fn sync_prefs(s: &Session) { *last = Some((folder.to_string(), s.plugin_dir.clone(), load_folder(s, folder))); } +/// The Additional Plug-ins Folder preference was cleared from `old`: when `old` is the folder last +/// loaded, it is forgotten, so setting the preference to it again loads it again. +pub(crate) fn forget_prefs_folder(old: &str) { + let mut last = FOLDER.lock().unwrap_or_else(|e| e.into_inner()); + if last.as_ref().is_some_and(|(f, _, _)| f == old.trim()) { + *last = None; + } +} + /// Turns Safe Mode on for `--safe-mode`, before the plug-in folder is attached: no plug-in loads or /// runs in this process from then on. pub fn start_in_safe_mode() { diff --git a/crates/engine/src/cmd/prefscmds.rs b/crates/engine/src/cmd/prefscmds.rs index 783ce0e91..a92b4095a 100644 --- a/crates/engine/src/cmd/prefscmds.rs +++ b/crates/engine/src/cmd/prefscmds.rs @@ -697,6 +697,9 @@ impl Session { let history_changed = p.history_states != self.prefs.history_states; let tile_edge_changed = p.pattern_tile_edge_color != self.prefs.pattern_tile_edge_color; let fonts_folder_changed = p.fonts_folder != self.prefs.fonts_folder; + if p.plugins_folder.trim().is_empty() && !self.prefs.plugins_folder.trim().is_empty() { + super::plugin::forget_prefs_folder(&self.prefs.plugins_folder); + } let hyphen_exceptions_changed = p.hyphenation_exceptions != self.prefs.hyphenation_exceptions; let corner_radius_changed = p.corner_radius != self.prefs.corner_radius; let lock_guides_changed = p.lock_guides_by_default != self.prefs.lock_guides_by_default; diff --git a/crates/engine/src/tests/plugins.rs b/crates/engine/src/tests/plugins.rs index 04e7b7784..3c647deb0 100644 --- a/crates/engine/src/tests/plugins.rs +++ b/crates/engine/src/tests/plugins.rs @@ -1315,6 +1315,25 @@ fn plugin_management_commands() { std::fs::remove_dir_all(&dir).ok(); } +/// Clearing the Additional Plug-ins Folder forgets the folder: setting the same folder again +/// installs what is in it, as setting any other folder does. +#[test] +fn plugins_folder_set_again_after_clearing_installs_its_plugins() { + let dir = crate::tests_links::Folder::new("plugin-folder-cleared"); + let id = "test.engine.foldercleared"; + let src = tpl::returning(&tpl::manifest(id, "filter", "{}"), r#"{"objects":[]}"#); + std::fs::write(dir.0.join("cleared.wasm"), wat::parse_str(src).unwrap()).unwrap(); + let mut s = session(); + let folder = json!({"key": "pluginsFolder", "value": dir.0.display().to_string()}); + run(&mut s, "prefs.set", folder.clone()); + assert!(vectorcraft_plugins::registry::get(id).is_some(), "installed from the folder"); + run(&mut s, "plugin.remove", json!({"id": id})); + run(&mut s, "prefs.set", json!({"key": "pluginsFolder", "value": ""})); + run(&mut s, "prefs.set", folder); + assert!(vectorcraft_plugins::registry::get(id).is_some(), "installed again when the folder is set again"); + run(&mut s, "plugin.remove", json!({"id": id})); +} + /// #2541: a plug-in installed in a session with a plug-in store is installed again in the next /// session that attaches the store, and Remove Plug-in takes it out of the store. #[test]