Fix attach modal showing local processes in SSH sessions (#37608)
Closes #37520 This change makes the attach modal load processes from the remote server when connecting via SSH, rather than showing local processes from the client machine. This works by using the new GetProcessesRequest RPC message to allow downstream clients to get the correct processes to display. It also only works with downstream ssh clients because the message handler is only registered on headless projects. Release Notes: - debugger: Fix bug where SSH attach modal showed local processes instead of processes from the server
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
use dap::{DapRegistry, DebugRequest};
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
use gpui::{AppContext, DismissEvent, Entity, EventEmitter, Focusable, Render};
|
||||
use gpui::{AppContext, DismissEvent, Entity, EventEmitter, Focusable, Render, Task};
|
||||
use gpui::{Subscription, WeakEntity};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use project::Project;
|
||||
use rpc::proto;
|
||||
use task::ZedDebugConfig;
|
||||
use util::debug_panic;
|
||||
|
||||
@@ -56,29 +58,28 @@ impl AttachModal {
|
||||
pub fn new(
|
||||
definition: ZedDebugConfig,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
project: Entity<Project>,
|
||||
modal: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let mut processes: Box<[_]> = System::new_all()
|
||||
.processes()
|
||||
.values()
|
||||
.map(|process| {
|
||||
let name = process.name().to_string_lossy().into_owned();
|
||||
Candidate {
|
||||
name: name.into(),
|
||||
pid: process.pid().as_u32(),
|
||||
command: process
|
||||
.cmd()
|
||||
.iter()
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
processes.sort_by_key(|k| k.name.clone());
|
||||
let processes = processes.into_iter().collect();
|
||||
Self::with_processes(workspace, definition, processes, modal, window, cx)
|
||||
let processes_task = get_processes_for_project(&project, cx);
|
||||
|
||||
let modal = Self::with_processes(workspace, definition, Arc::new([]), modal, window, cx);
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let processes = processes_task.await;
|
||||
this.update_in(cx, |modal, window, cx| {
|
||||
modal.picker.update(cx, |picker, cx| {
|
||||
picker.delegate.candidates = processes;
|
||||
picker.refresh(window, cx);
|
||||
});
|
||||
})?;
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
modal
|
||||
}
|
||||
|
||||
pub(super) fn with_processes(
|
||||
@@ -332,6 +333,57 @@ impl PickerDelegate for AttachModalDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_processes_for_project(project: &Entity<Project>, cx: &mut App) -> Task<Arc<[Candidate]>> {
|
||||
let project = project.read(cx);
|
||||
|
||||
if let Some(remote_client) = project.remote_client() {
|
||||
let proto_client = remote_client.read(cx).proto_client();
|
||||
cx.spawn(async move |_cx| {
|
||||
let response = proto_client
|
||||
.request(proto::GetProcesses {
|
||||
project_id: proto::REMOTE_SERVER_PROJECT_ID,
|
||||
})
|
||||
.await
|
||||
.unwrap_or_else(|_| proto::GetProcessesResponse {
|
||||
processes: Vec::new(),
|
||||
});
|
||||
|
||||
let mut processes: Vec<Candidate> = response
|
||||
.processes
|
||||
.into_iter()
|
||||
.map(|p| Candidate {
|
||||
pid: p.pid,
|
||||
name: p.name.into(),
|
||||
command: p.command,
|
||||
})
|
||||
.collect();
|
||||
|
||||
processes.sort_by_key(|k| k.name.clone());
|
||||
Arc::from(processes.into_boxed_slice())
|
||||
})
|
||||
} else {
|
||||
let mut processes: Box<[_]> = System::new_all()
|
||||
.processes()
|
||||
.values()
|
||||
.map(|process| {
|
||||
let name = process.name().to_string_lossy().into_owned();
|
||||
Candidate {
|
||||
name: name.into(),
|
||||
pid: process.pid().as_u32(),
|
||||
command: process
|
||||
.cmd()
|
||||
.iter()
|
||||
.map(|s| s.to_string_lossy().to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
processes.sort_by_key(|k| k.name.clone());
|
||||
let processes = processes.into_iter().collect();
|
||||
Task::ready(processes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub(crate) fn _process_names(modal: &AttachModal, cx: &mut Context<AttachModal>) -> Vec<String> {
|
||||
modal.picker.read_with(cx, |picker, _| {
|
||||
|
||||
Reference in New Issue
Block a user