Restructure remote client crate, consolidate SSH logic (#36967)

This is a pure refactor that consolidates all SSH remoting logic such
that it should be straightforward to add another transport to the
remoting system.

Release Notes:

- N/A

---------

Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
This commit is contained in:
Max Brunsfeld
2025-08-27 00:15:39 +00:00
committed by GitHub
co-authored by Mikayla Maki
parent d713390366
commit 1eae76e856
39 changed files with 3330 additions and 3411 deletions
+154 -155
View File
@@ -42,9 +42,7 @@ pub use manifest_tree::ManifestTree;
use anyhow::{Context as _, Result, anyhow};
use buffer_store::{BufferStore, BufferStoreEvent};
use client::{
Client, Collaborator, PendingEntitySubscription, ProjectId, TypedEnvelope, UserStore, proto,
};
use client::{Client, Collaborator, PendingEntitySubscription, TypedEnvelope, UserStore, proto};
use clock::ReplicaId;
use dap::client::DebugAdapterClient;
@@ -89,10 +87,10 @@ use node_runtime::NodeRuntime;
use parking_lot::Mutex;
pub use prettier_store::PrettierStore;
use project_settings::{ProjectSettings, SettingsObserver, SettingsObserverEvent};
use remote::{SshConnectionOptions, SshRemoteClient};
use remote::{RemoteClient, SshConnectionOptions};
use rpc::{
AnyProtoClient, ErrorCode,
proto::{FromProto, LanguageServerPromptResponse, SSH_PROJECT_ID, ToProto},
proto::{FromProto, LanguageServerPromptResponse, REMOTE_SERVER_PROJECT_ID, ToProto},
};
use search::{SearchInputKind, SearchQuery, SearchResult};
use search_history::SearchHistory;
@@ -177,12 +175,12 @@ pub struct Project {
dap_store: Entity<DapStore>,
breakpoint_store: Entity<BreakpointStore>,
client: Arc<client::Client>,
collab_client: Arc<client::Client>,
join_project_response_message_id: u32,
task_store: Entity<TaskStore>,
user_store: Entity<UserStore>,
fs: Arc<dyn Fs>,
ssh_client: Option<Entity<SshRemoteClient>>,
remote_client: Option<Entity<RemoteClient>>,
client_state: ProjectClientState,
git_store: Entity<GitStore>,
collaborators: HashMap<proto::PeerId, Collaborator>,
@@ -1154,12 +1152,12 @@ impl Project {
active_entry: None,
snippets,
languages,
client,
collab_client: client,
task_store,
user_store,
settings_observer,
fs,
ssh_client: None,
remote_client: None,
breakpoint_store,
dap_store,
@@ -1183,8 +1181,8 @@ impl Project {
})
}
pub fn ssh(
ssh: Entity<SshRemoteClient>,
pub fn remote(
remote: Entity<RemoteClient>,
client: Arc<Client>,
node: NodeRuntime,
user_store: Entity<UserStore>,
@@ -1200,10 +1198,15 @@ impl Project {
let snippets =
SnippetProvider::new(fs.clone(), BTreeSet::from_iter([global_snippets_dir]), cx);
let (ssh_proto, path_style) =
ssh.read_with(cx, |ssh, _| (ssh.proto_client(), ssh.path_style()));
let (remote_proto, path_style) =
remote.read_with(cx, |remote, _| (remote.proto_client(), remote.path_style()));
let worktree_store = cx.new(|_| {
WorktreeStore::remote(false, ssh_proto.clone(), SSH_PROJECT_ID, path_style)
WorktreeStore::remote(
false,
remote_proto.clone(),
REMOTE_SERVER_PROJECT_ID,
path_style,
)
});
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
.detach();
@@ -1215,31 +1218,32 @@ impl Project {
let buffer_store = cx.new(|cx| {
BufferStore::remote(
worktree_store.clone(),
ssh.read(cx).proto_client(),
SSH_PROJECT_ID,
remote.read(cx).proto_client(),
REMOTE_SERVER_PROJECT_ID,
cx,
)
});
let image_store = cx.new(|cx| {
ImageStore::remote(
worktree_store.clone(),
ssh.read(cx).proto_client(),
SSH_PROJECT_ID,
remote.read(cx).proto_client(),
REMOTE_SERVER_PROJECT_ID,
cx,
)
});
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
.detach();
let toolchain_store = cx
.new(|cx| ToolchainStore::remote(SSH_PROJECT_ID, ssh.read(cx).proto_client(), cx));
let toolchain_store = cx.new(|cx| {
ToolchainStore::remote(REMOTE_SERVER_PROJECT_ID, remote.read(cx).proto_client(), cx)
});
let task_store = cx.new(|cx| {
TaskStore::remote(
fs.clone(),
buffer_store.downgrade(),
worktree_store.clone(),
toolchain_store.read(cx).as_language_toolchain_store(),
ssh.read(cx).proto_client(),
SSH_PROJECT_ID,
remote.read(cx).proto_client(),
REMOTE_SERVER_PROJECT_ID,
cx,
)
});
@@ -1262,8 +1266,8 @@ impl Project {
buffer_store.clone(),
worktree_store.clone(),
languages.clone(),
ssh_proto.clone(),
SSH_PROJECT_ID,
remote_proto.clone(),
REMOTE_SERVER_PROJECT_ID,
fs.clone(),
cx,
)
@@ -1271,12 +1275,12 @@ impl Project {
cx.subscribe(&lsp_store, Self::on_lsp_store_event).detach();
let breakpoint_store =
cx.new(|_| BreakpointStore::remote(SSH_PROJECT_ID, ssh_proto.clone()));
cx.new(|_| BreakpointStore::remote(REMOTE_SERVER_PROJECT_ID, remote_proto.clone()));
let dap_store = cx.new(|cx| {
DapStore::new_ssh(
SSH_PROJECT_ID,
ssh.clone(),
DapStore::new_remote(
REMOTE_SERVER_PROJECT_ID,
remote.clone(),
breakpoint_store.clone(),
worktree_store.clone(),
cx,
@@ -1284,10 +1288,16 @@ impl Project {
});
let git_store = cx.new(|cx| {
GitStore::ssh(&worktree_store, buffer_store.clone(), ssh_proto.clone(), cx)
GitStore::remote(
&worktree_store,
buffer_store.clone(),
remote_proto.clone(),
REMOTE_SERVER_PROJECT_ID,
cx,
)
});
cx.subscribe(&ssh, Self::on_ssh_event).detach();
cx.subscribe(&remote, Self::on_remote_client_event).detach();
let this = Self {
buffer_ordered_messages_tx: tx,
@@ -1306,11 +1316,13 @@ impl Project {
_subscriptions: vec![
cx.on_release(Self::release),
cx.on_app_quit(|this, cx| {
let shutdown = this.ssh_client.take().and_then(|client| {
client.read(cx).shutdown_processes(
Some(proto::ShutdownRemoteServer {}),
cx.background_executor().clone(),
)
let shutdown = this.remote_client.take().and_then(|client| {
client.update(cx, |client, cx| {
client.shutdown_processes(
Some(proto::ShutdownRemoteServer {}),
cx.background_executor().clone(),
)
})
});
cx.background_executor().spawn(async move {
@@ -1323,12 +1335,12 @@ impl Project {
active_entry: None,
snippets,
languages,
client,
collab_client: client,
task_store,
user_store,
settings_observer,
fs,
ssh_client: Some(ssh.clone()),
remote_client: Some(remote.clone()),
buffers_needing_diff: Default::default(),
git_diff_debouncer: DebouncedDelay::new(),
terminals: Terminals {
@@ -1346,52 +1358,34 @@ impl Project {
agent_location: None,
};
// ssh -> local machine handlers
ssh_proto.subscribe_to_entity(SSH_PROJECT_ID, &cx.entity());
ssh_proto.subscribe_to_entity(SSH_PROJECT_ID, &this.buffer_store);
ssh_proto.subscribe_to_entity(SSH_PROJECT_ID, &this.worktree_store);
ssh_proto.subscribe_to_entity(SSH_PROJECT_ID, &this.lsp_store);
ssh_proto.subscribe_to_entity(SSH_PROJECT_ID, &this.dap_store);
ssh_proto.subscribe_to_entity(SSH_PROJECT_ID, &this.settings_observer);
ssh_proto.subscribe_to_entity(SSH_PROJECT_ID, &this.git_store);
// remote server -> local machine handlers
remote_proto.subscribe_to_entity(REMOTE_SERVER_PROJECT_ID, &cx.entity());
remote_proto.subscribe_to_entity(REMOTE_SERVER_PROJECT_ID, &this.buffer_store);
remote_proto.subscribe_to_entity(REMOTE_SERVER_PROJECT_ID, &this.worktree_store);
remote_proto.subscribe_to_entity(REMOTE_SERVER_PROJECT_ID, &this.lsp_store);
remote_proto.subscribe_to_entity(REMOTE_SERVER_PROJECT_ID, &this.dap_store);
remote_proto.subscribe_to_entity(REMOTE_SERVER_PROJECT_ID, &this.settings_observer);
remote_proto.subscribe_to_entity(REMOTE_SERVER_PROJECT_ID, &this.git_store);
ssh_proto.add_entity_message_handler(Self::handle_create_buffer_for_peer);
ssh_proto.add_entity_message_handler(Self::handle_update_worktree);
ssh_proto.add_entity_message_handler(Self::handle_update_project);
ssh_proto.add_entity_message_handler(Self::handle_toast);
ssh_proto.add_entity_request_handler(Self::handle_language_server_prompt_request);
ssh_proto.add_entity_message_handler(Self::handle_hide_toast);
ssh_proto.add_entity_request_handler(Self::handle_update_buffer_from_ssh);
BufferStore::init(&ssh_proto);
LspStore::init(&ssh_proto);
SettingsObserver::init(&ssh_proto);
TaskStore::init(Some(&ssh_proto));
ToolchainStore::init(&ssh_proto);
DapStore::init(&ssh_proto, cx);
GitStore::init(&ssh_proto);
remote_proto.add_entity_message_handler(Self::handle_create_buffer_for_peer);
remote_proto.add_entity_message_handler(Self::handle_update_worktree);
remote_proto.add_entity_message_handler(Self::handle_update_project);
remote_proto.add_entity_message_handler(Self::handle_toast);
remote_proto.add_entity_request_handler(Self::handle_language_server_prompt_request);
remote_proto.add_entity_message_handler(Self::handle_hide_toast);
remote_proto.add_entity_request_handler(Self::handle_update_buffer_from_remote_server);
BufferStore::init(&remote_proto);
LspStore::init(&remote_proto);
SettingsObserver::init(&remote_proto);
TaskStore::init(Some(&remote_proto));
ToolchainStore::init(&remote_proto);
DapStore::init(&remote_proto, cx);
GitStore::init(&remote_proto);
this
})
}
pub async fn remote(
remote_id: u64,
client: Arc<Client>,
user_store: Entity<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
cx: AsyncApp,
) -> Result<Entity<Self>> {
let project =
Self::in_room(remote_id, client, user_store, languages, fs, cx.clone()).await?;
cx.update(|cx| {
connection_manager::Manager::global(cx).update(cx, |manager, cx| {
manager.maintain_project_connection(&project, cx)
})
})?;
Ok(project)
}
pub async fn in_room(
remote_id: u64,
client: Arc<Client>,
@@ -1523,7 +1517,7 @@ impl Project {
&worktree_store,
buffer_store.clone(),
client.clone().into(),
ProjectId(remote_id),
remote_id,
cx,
)
})?;
@@ -1574,11 +1568,11 @@ impl Project {
task_store,
snippets,
fs,
ssh_client: None,
remote_client: None,
settings_observer: settings_observer.clone(),
client_subscriptions: Default::default(),
_subscriptions: vec![cx.on_release(Self::release)],
client: client.clone(),
collab_client: client.clone(),
client_state: ProjectClientState::Remote {
sharing_has_stopped: false,
capability: Capability::ReadWrite,
@@ -1661,11 +1655,13 @@ impl Project {
}
fn release(&mut self, cx: &mut App) {
if let Some(client) = self.ssh_client.take() {
let shutdown = client.read(cx).shutdown_processes(
Some(proto::ShutdownRemoteServer {}),
cx.background_executor().clone(),
);
if let Some(client) = self.remote_client.take() {
let shutdown = client.update(cx, |client, cx| {
client.shutdown_processes(
Some(proto::ShutdownRemoteServer {}),
cx.background_executor().clone(),
)
});
cx.background_spawn(async move {
if let Some(shutdown) = shutdown {
@@ -1681,7 +1677,7 @@ impl Project {
let _ = self.unshare_internal(cx);
}
ProjectClientState::Remote { remote_id, .. } => {
let _ = self.client.send(proto::LeaveProject {
let _ = self.collab_client.send(proto::LeaveProject {
project_id: *remote_id,
});
self.disconnected_from_host_internal(cx);
@@ -1808,11 +1804,11 @@ impl Project {
}
pub fn client(&self) -> Arc<Client> {
self.client.clone()
self.collab_client.clone()
}
pub fn ssh_client(&self) -> Option<Entity<SshRemoteClient>> {
self.ssh_client.clone()
pub fn remote_client(&self) -> Option<Entity<RemoteClient>> {
self.remote_client.clone()
}
pub fn user_store(&self) -> Entity<UserStore> {
@@ -1893,30 +1889,30 @@ impl Project {
if self.is_local() {
return true;
}
if self.is_via_ssh() {
if self.is_via_remote_server() {
return true;
}
false
}
pub fn ssh_connection_state(&self, cx: &App) -> Option<remote::ConnectionState> {
self.ssh_client
pub fn remote_connection_state(&self, cx: &App) -> Option<remote::ConnectionState> {
self.remote_client
.as_ref()
.map(|ssh| ssh.read(cx).connection_state())
.map(|remote| remote.read(cx).connection_state())
}
pub fn ssh_connection_options(&self, cx: &App) -> Option<SshConnectionOptions> {
self.ssh_client
pub fn remote_connection_options(&self, cx: &App) -> Option<SshConnectionOptions> {
self.remote_client
.as_ref()
.map(|ssh| ssh.read(cx).connection_options())
.map(|remote| remote.read(cx).connection_options())
}
pub fn replica_id(&self) -> ReplicaId {
match self.client_state {
ProjectClientState::Remote { replica_id, .. } => replica_id,
_ => {
if self.ssh_client.is_some() {
if self.remote_client.is_some() {
1
} else {
0
@@ -2220,55 +2216,55 @@ impl Project {
);
self.client_subscriptions.extend([
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&cx.entity(), &cx.to_async()),
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&self.worktree_store, &cx.to_async()),
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&self.buffer_store, &cx.to_async()),
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&self.lsp_store, &cx.to_async()),
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&self.settings_observer, &cx.to_async()),
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&self.dap_store, &cx.to_async()),
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&self.breakpoint_store, &cx.to_async()),
self.client
self.collab_client
.subscribe_to_entity(project_id)?
.set_entity(&self.git_store, &cx.to_async()),
]);
self.buffer_store.update(cx, |buffer_store, cx| {
buffer_store.shared(project_id, self.client.clone().into(), cx)
buffer_store.shared(project_id, self.collab_client.clone().into(), cx)
});
self.worktree_store.update(cx, |worktree_store, cx| {
worktree_store.shared(project_id, self.client.clone().into(), cx);
worktree_store.shared(project_id, self.collab_client.clone().into(), cx);
});
self.lsp_store.update(cx, |lsp_store, cx| {
lsp_store.shared(project_id, self.client.clone().into(), cx)
lsp_store.shared(project_id, self.collab_client.clone().into(), cx)
});
self.breakpoint_store.update(cx, |breakpoint_store, _| {
breakpoint_store.shared(project_id, self.client.clone().into())
breakpoint_store.shared(project_id, self.collab_client.clone().into())
});
self.dap_store.update(cx, |dap_store, cx| {
dap_store.shared(project_id, self.client.clone().into(), cx);
dap_store.shared(project_id, self.collab_client.clone().into(), cx);
});
self.task_store.update(cx, |task_store, cx| {
task_store.shared(project_id, self.client.clone().into(), cx);
task_store.shared(project_id, self.collab_client.clone().into(), cx);
});
self.settings_observer.update(cx, |settings_observer, cx| {
settings_observer.shared(project_id, self.client.clone().into(), cx)
settings_observer.shared(project_id, self.collab_client.clone().into(), cx)
});
self.git_store.update(cx, |git_store, cx| {
git_store.shared(project_id, self.client.clone().into(), cx)
git_store.shared(project_id, self.collab_client.clone().into(), cx)
});
self.client_state = ProjectClientState::Shared {
@@ -2293,7 +2289,7 @@ impl Project {
});
if let Some(remote_id) = self.remote_id() {
self.git_store.update(cx, |git_store, cx| {
git_store.shared(remote_id, self.client.clone().into(), cx)
git_store.shared(remote_id, self.collab_client.clone().into(), cx)
});
}
cx.emit(Event::Reshared);
@@ -2370,7 +2366,7 @@ impl Project {
git_store.unshared(cx);
});
self.client
self.collab_client
.send(proto::UnshareProject {
project_id: remote_id,
})
@@ -2437,15 +2433,17 @@ impl Project {
sharing_has_stopped,
..
} => *sharing_has_stopped,
ProjectClientState::Local if self.is_via_ssh() => self.ssh_is_disconnected(cx),
ProjectClientState::Local if self.is_via_remote_server() => {
self.remote_client_is_disconnected(cx)
}
_ => false,
}
}
fn ssh_is_disconnected(&self, cx: &App) -> bool {
self.ssh_client
fn remote_client_is_disconnected(&self, cx: &App) -> bool {
self.remote_client
.as_ref()
.map(|ssh| ssh.read(cx).is_disconnected())
.map(|remote| remote.read(cx).is_disconnected())
.unwrap_or(false)
}
@@ -2463,16 +2461,16 @@ impl Project {
pub fn is_local(&self) -> bool {
match &self.client_state {
ProjectClientState::Local | ProjectClientState::Shared { .. } => {
self.ssh_client.is_none()
self.remote_client.is_none()
}
ProjectClientState::Remote { .. } => false,
}
}
pub fn is_via_ssh(&self) -> bool {
pub fn is_via_remote_server(&self) -> bool {
match &self.client_state {
ProjectClientState::Local | ProjectClientState::Shared { .. } => {
self.ssh_client.is_some()
self.remote_client.is_some()
}
ProjectClientState::Remote { .. } => false,
}
@@ -2496,7 +2494,7 @@ impl Project {
language: Option<Arc<Language>>,
cx: &mut Context<Self>,
) -> Entity<Buffer> {
if self.is_via_collab() || self.is_via_ssh() {
if self.is_via_collab() || self.is_via_remote_server() {
panic!("called create_local_buffer on a remote project")
}
self.buffer_store.update(cx, |buffer_store, cx| {
@@ -2620,10 +2618,10 @@ impl Project {
) -> Task<Result<Entity<Buffer>>> {
if let Some(buffer) = self.buffer_for_id(id, cx) {
Task::ready(Ok(buffer))
} else if self.is_local() || self.is_via_ssh() {
} else if self.is_local() || self.is_via_remote_server() {
Task::ready(Err(anyhow!("buffer {id} does not exist")))
} else if let Some(project_id) = self.remote_id() {
let request = self.client.request(proto::OpenBufferById {
let request = self.collab_client.request(proto::OpenBufferById {
project_id,
id: id.into(),
});
@@ -2741,7 +2739,7 @@ impl Project {
for (buffer_id, operations) in operations_by_buffer_id.drain() {
let request = this.read_with(cx, |this, _| {
let project_id = this.remote_id()?;
Some(this.client.request(proto::UpdateBuffer {
Some(this.collab_client.request(proto::UpdateBuffer {
buffer_id: buffer_id.into(),
project_id,
operations,
@@ -2808,7 +2806,7 @@ impl Project {
project.read_with(cx, |project, _| {
if let Some(project_id) = project.remote_id() {
project
.client
.collab_client
.send(proto::UpdateLanguageServer {
project_id,
server_name: name.map(|name| String::from(name.0)),
@@ -2846,8 +2844,8 @@ impl Project {
self.register_buffer(buffer, cx).log_err();
}
BufferStoreEvent::BufferDropped(buffer_id) => {
if let Some(ref ssh_client) = self.ssh_client {
ssh_client
if let Some(ref remote_client) = self.remote_client {
remote_client
.read(cx)
.proto_client()
.send(proto::CloseBuffer {
@@ -2995,16 +2993,14 @@ impl Project {
}
}
fn on_ssh_event(
fn on_remote_client_event(
&mut self,
_: Entity<SshRemoteClient>,
event: &remote::SshRemoteEvent,
_: Entity<RemoteClient>,
event: &remote::RemoteClientEvent,
cx: &mut Context<Self>,
) {
match event {
remote::SshRemoteEvent::Disconnected => {
// if self.is_via_ssh() {
// self.collaborators.clear();
remote::RemoteClientEvent::Disconnected => {
self.worktree_store.update(cx, |store, cx| {
store.disconnected_from_host(cx);
});
@@ -3110,8 +3106,9 @@ impl Project {
}
fn on_worktree_released(&mut self, id_to_remove: WorktreeId, cx: &mut Context<Self>) {
if let Some(ssh) = &self.ssh_client {
ssh.read(cx)
if let Some(remote) = &self.remote_client {
remote
.read(cx)
.proto_client()
.send(proto::RemoveWorktree {
worktree_id: id_to_remove.to_proto(),
@@ -3144,8 +3141,9 @@ impl Project {
} => {
let operation = language::proto::serialize_operation(operation);
if let Some(ssh) = &self.ssh_client {
ssh.read(cx)
if let Some(remote) = &self.remote_client {
remote
.read(cx)
.proto_client()
.send(proto::UpdateBuffer {
project_id: 0,
@@ -3552,16 +3550,16 @@ impl Project {
pub fn open_server_settings(&mut self, cx: &mut Context<Self>) -> Task<Result<Entity<Buffer>>> {
let guard = self.retain_remotely_created_models(cx);
let Some(ssh_client) = self.ssh_client.as_ref() else {
let Some(remote) = self.remote_client.as_ref() else {
return Task::ready(Err(anyhow!("not an ssh project")));
};
let proto_client = ssh_client.read(cx).proto_client();
let proto_client = remote.read(cx).proto_client();
cx.spawn(async move |project, cx| {
let buffer = proto_client
.request(proto::OpenServerSettings {
project_id: SSH_PROJECT_ID,
project_id: REMOTE_SERVER_PROJECT_ID,
})
.await?;
@@ -3948,10 +3946,11 @@ impl Project {
) -> Receiver<Entity<Buffer>> {
let (tx, rx) = smol::channel::unbounded();
let (client, remote_id): (AnyProtoClient, _) = if let Some(ssh_client) = &self.ssh_client {
let (client, remote_id): (AnyProtoClient, _) = if let Some(ssh_client) = &self.remote_client
{
(ssh_client.read(cx).proto_client(), 0)
} else if let Some(remote_id) = self.remote_id() {
(self.client.clone().into(), remote_id)
(self.collab_client.clone().into(), remote_id)
} else {
return rx;
};
@@ -4095,14 +4094,14 @@ impl Project {
is_dir: metadata.is_dir,
})
})
} else if let Some(ssh_client) = self.ssh_client.as_ref() {
} else if let Some(ssh_client) = self.remote_client.as_ref() {
let path_style = ssh_client.read(cx).path_style();
let request_path = RemotePathBuf::from_str(path, path_style);
let request = ssh_client
.read(cx)
.proto_client()
.request(proto::GetPathMetadata {
project_id: SSH_PROJECT_ID,
project_id: REMOTE_SERVER_PROJECT_ID,
path: request_path.to_proto(),
});
cx.background_spawn(async move {
@@ -4202,10 +4201,10 @@ impl Project {
) -> Task<Result<Vec<DirectoryItem>>> {
if self.is_local() {
DirectoryLister::Local(cx.entity(), self.fs.clone()).list_directory(query, cx)
} else if let Some(session) = self.ssh_client.as_ref() {
} else if let Some(session) = self.remote_client.as_ref() {
let path_buf = PathBuf::from(query);
let request = proto::ListRemoteDirectory {
dev_server_id: SSH_PROJECT_ID,
dev_server_id: REMOTE_SERVER_PROJECT_ID,
path: path_buf.to_proto(),
config: Some(proto::ListRemoteDirectoryConfig { is_dir: true }),
};
@@ -4420,7 +4419,7 @@ impl Project {
mut cx: AsyncApp,
) -> Result<()> {
this.update(&mut cx, |this, cx| {
if this.is_local() || this.is_via_ssh() {
if this.is_local() || this.is_via_remote_server() {
this.unshare(cx)?;
} else {
this.disconnected_from_host(cx);
@@ -4629,7 +4628,7 @@ impl Project {
})?
}
async fn handle_update_buffer_from_ssh(
async fn handle_update_buffer_from_remote_server(
this: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateBuffer>,
cx: AsyncApp,
@@ -4638,7 +4637,7 @@ impl Project {
if let Some(remote_id) = this.remote_id() {
let mut payload = envelope.payload.clone();
payload.project_id = remote_id;
cx.background_spawn(this.client.request(payload))
cx.background_spawn(this.collab_client.request(payload))
.detach_and_log_err(cx);
}
this.buffer_store.clone()
@@ -4652,9 +4651,9 @@ impl Project {
cx: AsyncApp,
) -> Result<proto::Ack> {
let buffer_store = this.read_with(&cx, |this, cx| {
if let Some(ssh) = &this.ssh_client {
if let Some(ssh) = &this.remote_client {
let mut payload = envelope.payload.clone();
payload.project_id = SSH_PROJECT_ID;
payload.project_id = REMOTE_SERVER_PROJECT_ID;
cx.background_spawn(ssh.read(cx).proto_client().request(payload))
.detach_and_log_err(cx);
}
@@ -4704,7 +4703,7 @@ impl Project {
mut cx: AsyncApp,
) -> Result<proto::SynchronizeBuffersResponse> {
let response = this.update(&mut cx, |this, cx| {
let client = this.client.clone();
let client = this.collab_client.clone();
this.buffer_store.update(cx, |this, cx| {
this.handle_synchronize_buffers(envelope, cx, client)
})
@@ -4841,7 +4840,7 @@ impl Project {
}
};
let client = self.client.clone();
let client = self.collab_client.clone();
cx.spawn(async move |this, cx| {
let (buffers, incomplete_buffer_ids) = this.update(cx, |this, cx| {
this.buffer_store.read(cx).buffer_version_info(cx)