From 04223f304bf6727728fc89056f7956a044af99ce Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 12 Jun 2025 01:40:41 +0200 Subject: [PATCH] debugger: Fix DebugAdapterDelegate::worktree_root always using the first visible worktree (#32585) Closes #32577 Release Notes: - Fixed debugger malfunctioning when using ZED_WORKTREE_ROOT env variable in multi-worktree workspaces. --- crates/debugger_ui/src/debugger_panel.rs | 15 ++++++++++- crates/project/src/debugger/dap_store.rs | 34 +++++++++++++++++------- crates/proto/proto/debugger.proto | 1 + crates/tasks_ui/src/tasks_ui.rs | 10 ++++--- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/crates/debugger_ui/src/debugger_panel.rs b/crates/debugger_ui/src/debugger_panel.rs index d686206ab0..c93e70541a 100644 --- a/crates/debugger_ui/src/debugger_panel.rs +++ b/crates/debugger_ui/src/debugger_panel.rs @@ -179,6 +179,19 @@ impl DebugPanel { cx, ) }); + let worktree = worktree_id.or_else(|| { + active_buffer + .as_ref() + .and_then(|buffer| buffer.read(cx).file()) + .map(|f| f.worktree_id(cx)) + }); + let Some(worktree) = worktree + .and_then(|id| self.project.read(cx).worktree_for_id(id, cx)) + .or_else(|| self.project.read(cx).visible_worktrees(cx).next()) + else { + log::debug!("Could not find a worktree to spawn the debug session in"); + return; + }; self.debug_scenario_scheduled_last = true; if let Some(inventory) = self .project @@ -213,7 +226,7 @@ impl DebugPanel { .await?; dap_store .update(cx, |dap_store, cx| { - dap_store.boot_session(session.clone(), definition, cx) + dap_store.boot_session(session.clone(), definition, worktree, cx) })? .await } diff --git a/crates/project/src/debugger/dap_store.rs b/crates/project/src/debugger/dap_store.rs index b2a9fc0036..713ec5b838 100644 --- a/crates/project/src/debugger/dap_store.rs +++ b/crates/project/src/debugger/dap_store.rs @@ -180,15 +180,12 @@ impl DapStore { &mut self, definition: DebugTaskDefinition, session_id: SessionId, + worktree: &Entity, console: UnboundedSender, cx: &mut Context, ) -> Task> { match &self.mode { DapStoreMode::Local(_) => { - let Some(worktree) = self.worktree_store.read(cx).visible_worktrees(cx).next() - else { - return Task::ready(Err(anyhow!("Failed to find a worktree"))); - }; let Some(adapter) = DapRegistry::global(cx).adapter(&definition.adapter) else { return Task::ready(Err(anyhow!("Failed to find a debug adapter"))); }; @@ -229,6 +226,7 @@ impl DapStore { let request = ssh.upstream_client.request(proto::GetDebugAdapterBinary { session_id: session_id.to_proto(), project_id: ssh.upstream_project_id, + worktree_id: worktree.read(cx).id().to_proto(), definition: Some(definition.to_proto()), }); let ssh_client = ssh.ssh_client.clone(); @@ -401,12 +399,9 @@ impl DapStore { &self, session: Entity, definition: DebugTaskDefinition, + worktree: Entity, cx: &mut Context, ) -> Task> { - let Some(worktree) = self.worktree_store.read(cx).visible_worktrees(cx).next() else { - return Task::ready(Err(anyhow!("Failed to find a worktree"))); - }; - let dap_store = cx.weak_entity(); let console = session.update(cx, |session, cx| session.console_output(cx)); let session_id = session.read(cx).session_id(); @@ -416,7 +411,13 @@ impl DapStore { async move |this, cx| { let binary = this .update(cx, |this, cx| { - this.get_debug_adapter_binary(definition.clone(), session_id, console, cx) + this.get_debug_adapter_binary( + definition.clone(), + session_id, + &worktree, + console, + cx, + ) })? .await?; session @@ -780,9 +781,22 @@ impl DapStore { }) .detach(); + let worktree = this + .update(&mut cx, |this, cx| { + this.worktree_store + .read(cx) + .worktree_for_id(WorktreeId::from_proto(envelope.payload.worktree_id), cx) + })? + .context("Failed to find worktree with a given ID")?; let binary = this .update(&mut cx, |this, cx| { - this.get_debug_adapter_binary(definition, SessionId::from_proto(session_id), tx, cx) + this.get_debug_adapter_binary( + definition, + SessionId::from_proto(session_id), + &worktree, + tx, + cx, + ) })? .await?; Ok(binary.to_proto()) diff --git a/crates/proto/proto/debugger.proto b/crates/proto/proto/debugger.proto index bc82812201..3979265acc 100644 --- a/crates/proto/proto/debugger.proto +++ b/crates/proto/proto/debugger.proto @@ -493,6 +493,7 @@ message GetDebugAdapterBinary { uint64 project_id = 1; uint64 session_id = 3; DebugTaskDefinition definition = 2; + uint64 worktree_id = 4; } message DebugAdapterBinary { diff --git a/crates/tasks_ui/src/tasks_ui.rs b/crates/tasks_ui/src/tasks_ui.rs index 9b5026ad01..f0131b52a0 100644 --- a/crates/tasks_ui/src/tasks_ui.rs +++ b/crates/tasks_ui/src/tasks_ui.rs @@ -285,10 +285,12 @@ pub fn task_contexts( .worktree_for_id(*worktree_id, cx) .map_or(false, |worktree| is_visible_directory(&worktree, cx)) }) - .or(workspace - .visible_worktrees(cx) - .next() - .map(|tree| tree.read(cx).id())); + .or_else(|| { + workspace + .visible_worktrees(cx) + .next() + .map(|tree| tree.read(cx).id()) + }); let active_editor = active_item.and_then(|item| item.act_as::(cx));