From d74ba8ca9e49d9d94a4e59a0ee0bdbd1128af76e Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Thu, 18 Jun 2026 16:05:05 +0300 Subject: fix: emit plugin lifecycle events from ui worktree flows refs #662 --- src/app/api/plugins/context.rs | 49 +++++++++++++++++++++-------- src/app/api/plugins/mod.rs | 70 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 12 deletions(-) (limited to 'src/app/api/plugins') diff --git a/src/app/api/plugins/context.rs b/src/app/api/plugins/context.rs index cd7d1818..92d0d4c6 100644 --- a/src/app/api/plugins/context.rs +++ b/src/app/api/plugins/context.rs @@ -63,14 +63,31 @@ impl App { }) }), EventData::WorkspaceRenamed { workspace_id, .. } - | EventData::WorkspaceFocused { workspace_id } - | EventData::WorktreeRemoved { workspace_id, .. } => self + | EventData::WorkspaceFocused { workspace_id } => self .plugin_context_for_workspace_id(workspace_id, correlation_id) .unwrap_or_else(|| { let mut context = empty_plugin_context(correlation_id); context.workspace_id = Some(workspace_id.clone()); context }), + EventData::WorktreeRemoved { + workspace_id, + workspace, + worktree, + .. + } => workspace + .as_ref() + .map(|workspace| { + self.plugin_context_for_workspace_snapshot(workspace, correlation_id) + }) + .or_else(|| self.plugin_context_for_workspace_id(workspace_id, correlation_id)) + .unwrap_or_else(|| { + let mut context = empty_plugin_context(correlation_id); + context.workspace_id = Some(workspace_id.clone()); + context.workspace_label = Some(worktree.label.clone()); + context.workspace_cwd = Some(worktree.path.clone()); + context + }), EventData::TabCreated { tab } => self.plugin_context_for_tab_info(tab, correlation_id), EventData::TabClosed { tab_id, @@ -168,19 +185,27 @@ impl App { ) -> PluginInvocationContext { self.plugin_context_for_workspace_id(&workspace.workspace_id, correlation_id) .unwrap_or_else(|| { - let mut context = empty_plugin_context(correlation_id); - context.workspace_id = Some(workspace.workspace_id.clone()); - context.workspace_label = Some(workspace.label.clone()); - context.workspace_cwd = workspace - .worktree - .as_ref() - .map(|worktree| worktree.checkout_path.clone()); - context.worktree = workspace.worktree.clone(); - context.tab_id = Some(workspace.active_tab_id.clone()); - context + self.plugin_context_for_workspace_snapshot(workspace, correlation_id) }) } + fn plugin_context_for_workspace_snapshot( + &self, + workspace: &crate::api::schema::WorkspaceInfo, + correlation_id: &str, + ) -> PluginInvocationContext { + let mut context = empty_plugin_context(correlation_id); + context.workspace_id = Some(workspace.workspace_id.clone()); + context.workspace_label = Some(workspace.label.clone()); + context.workspace_cwd = workspace + .worktree + .as_ref() + .map(|worktree| worktree.checkout_path.clone()); + context.worktree = workspace.worktree.clone(); + context.tab_id = Some(workspace.active_tab_id.clone()); + context + } + fn plugin_context_for_tab_id( &self, tab_id: &str, diff --git a/src/app/api/plugins/mod.rs b/src/app/api/plugins/mod.rs index 8c0e4212..833134b5 100644 --- a/src/app/api/plugins/mod.rs +++ b/src/app/api/plugins/mod.rs @@ -1906,6 +1906,76 @@ command = ["sh", "-c", "printf '%s' \"$HERDR_PLUGIN_CONTEXT_JSON\" > {}"] pane_context.focused_pane_id.as_deref(), Some(active_public_pane_id.as_str()) ); + + app.state.workspaces[0].worktree_space = Some(crate::workspace::WorktreeSpaceMembership { + key: "repo-key".into(), + label: "herdr".into(), + repo_root: "/repo/herdr".into(), + checkout_path: "/repo/herdr-issue".into(), + is_linked_worktree: true, + }); + let workspace = app.workspace_info(0); + let worktree = crate::api::schema::WorktreeInfo { + path: "/repo/herdr-issue".into(), + branch: Some("worktree/issue".into()), + is_bare: false, + is_detached: false, + is_prunable: false, + is_linked_worktree: true, + open_workspace_id: None, + label: "herdr".into(), + }; + app.state.workspaces[0].worktree_space = Some(crate::workspace::WorktreeSpaceMembership { + key: "repo-key".into(), + label: "herdr".into(), + repo_root: "/repo/herdr".into(), + checkout_path: "/repo/herdr-other".into(), + is_linked_worktree: true, + }); + let changed_context = app.plugin_context_for_event( + &crate::api::schema::EventEnvelope { + event: crate::api::schema::EventKind::WorktreeRemoved, + data: crate::api::schema::EventData::WorktreeRemoved { + workspace_id: workspace_id.clone(), + workspace: Some(workspace.clone()), + worktree: worktree.clone(), + forced: true, + }, + }, + "worktree.removed", + ); + assert_eq!( + changed_context + .worktree + .as_ref() + .map(|worktree| worktree.checkout_path.as_str()), + Some("/repo/herdr-issue") + ); + + app.state.workspaces.clear(); + let removed_context = app.plugin_context_for_event( + &crate::api::schema::EventEnvelope { + event: crate::api::schema::EventKind::WorktreeRemoved, + data: crate::api::schema::EventData::WorktreeRemoved { + workspace_id: workspace_id.clone(), + workspace: Some(workspace), + worktree, + forced: true, + }, + }, + "worktree.removed", + ); + assert_eq!( + removed_context.workspace_id.as_deref(), + Some(workspace_id.as_str()) + ); + assert_eq!( + removed_context + .worktree + .as_ref() + .map(|worktree| worktree.checkout_path.as_str()), + Some("/repo/herdr-issue") + ); } #[cfg(unix)] -- cgit v1.2.3