diff --git a/Cargo.lock b/Cargo.lock index 5dbc9160528e3f4296db56cd10e35d4d9db7a654..b2c5500f9482fc9d31b7bfebccc21d0d92bae010 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14742,7 +14742,6 @@ dependencies = [ "parking_lot", "postage", "project", - "release_channel", "remote", "schemars", "serde", diff --git a/crates/recent_projects/src/remote_servers.rs b/crates/recent_projects/src/remote_servers.rs index 1b83120eb36faf5a8fe6f76c0e1e83b7d0346602..7aae9ceee81c4ea3807b0dea52262169946c4594 100644 --- a/crates/recent_projects/src/remote_servers.rs +++ b/crates/recent_projects/src/remote_servers.rs @@ -16,6 +16,7 @@ use gpui::{ }; use picker::Picker; use project::Project; +use remote::ssh_session::ConnectionIdentifier; use remote::SshConnectionOptions; use remote::SshRemoteClient; use settings::update_settings_file; @@ -413,7 +414,7 @@ impl RemoteServerProjects { let ssh_prompt = cx.new_view(|cx| SshPrompt::new(&connection_options, cx)); let connection = connect_over_ssh( - connection_options.remote_server_identifier(), + ConnectionIdentifier::Setup, connection_options.clone(), ssh_prompt.clone(), cx, @@ -501,7 +502,7 @@ impl RemoteServerProjects { .clone(); let connect = connect_over_ssh( - connection_options.remote_server_identifier(), + ConnectionIdentifier::Setup, connection_options.clone(), prompt, cx, diff --git a/crates/recent_projects/src/ssh_connections.rs b/crates/recent_projects/src/ssh_connections.rs index 0d40da375b72d3ae06dfbd22f9932bb250b379bd..4b409085ba9b84dc84126ea693195c321a3a3f9d 100644 --- a/crates/recent_projects/src/ssh_connections.rs +++ b/crates/recent_projects/src/ssh_connections.rs @@ -14,6 +14,7 @@ use gpui::{AppContext, Model}; use language::CursorShape; use markdown::{Markdown, MarkdownStyle}; use release_channel::ReleaseChannel; +use remote::ssh_session::ConnectionIdentifier; use remote::{SshConnectionOptions, SshPlatform, SshRemoteClient}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -534,7 +535,7 @@ pub fn is_connecting_over_ssh(workspace: &Workspace, cx: &AppContext) -> bool { } pub fn connect_over_ssh( - unique_identifier: String, + unique_identifier: ConnectionIdentifier, connection_options: SshConnectionOptions, ui: View, cx: &mut WindowContext, diff --git a/crates/remote/src/ssh_session.rs b/crates/remote/src/ssh_session.rs index 9cae283749828c5ea70555d0d56230ffa6cfcc5c..0c49361adc773f05799c43de97cd1bec6bb83fa2 100644 --- a/crates/remote/src/ssh_session.rs +++ b/crates/remote/src/ssh_session.rs @@ -202,17 +202,6 @@ impl SshConnectionOptions { host } } - - // Uniquely identifies dev server projects on a remote host. Needs to be - // stable for the same dev server project. - pub fn remote_server_identifier(&self) -> String { - let mut identifier = format!("dev-server-{:?}", self.host); - if let Some(username) = self.username.as_ref() { - identifier.push('-'); - identifier.push_str(&username); - } - identifier - } } #[derive(Copy, Clone, Debug)] @@ -520,14 +509,43 @@ pub enum SshRemoteEvent { impl EventEmitter for SshRemoteClient {} +// Identifies the socket on the remote server so that reconnects +// can re-join the same project. +pub enum ConnectionIdentifier { + Setup, + Workspace(i64), +} + +impl ConnectionIdentifier { + // This string gets used in a socket name, and so must be relatively short. + // The total length of: + // /home/{username}/.local/share/zed/server_state/{name}/stdout.sock + // Must be less than about 100 characters + // https://unix.stackexchange.com/questions/367008/why-is-socket-path-length-limited-to-a-hundred-chars + // So our strings should be at most 20 characters or so. + fn to_string(&self, cx: &AppContext) -> String { + let identifier_prefix = match ReleaseChannel::global(cx) { + ReleaseChannel::Stable => "".to_string(), + release_channel => format!("{}-", release_channel.dev_name()), + }; + match self { + Self::Setup => format!("{identifier_prefix}setup"), + Self::Workspace(workspace_id) => { + format!("{identifier_prefix}workspace-{workspace_id}",) + } + } + } +} + impl SshRemoteClient { pub fn new( - unique_identifier: String, + unique_identifier: ConnectionIdentifier, connection_options: SshConnectionOptions, cancellation: oneshot::Receiver<()>, delegate: Arc, cx: &mut AppContext, ) -> Task>>> { + let unique_identifier = unique_identifier.to_string(cx); cx.spawn(|mut cx| async move { let success = Box::pin(async move { let (outgoing_tx, outgoing_rx) = mpsc::unbounded::(); @@ -1096,7 +1114,15 @@ impl SshRemoteClient { ) -> Model { let (_tx, rx) = oneshot::channel(); client_cx - .update(|cx| Self::new("fake".to_string(), opts, rx, Arc::new(fake::Delegate), cx)) + .update(|cx| { + Self::new( + ConnectionIdentifier::Setup, + opts, + rx, + Arc::new(fake::Delegate), + cx, + ) + }) .await .unwrap() .unwrap() diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index 2554aa48d2eb3d1840db7d2dcf60fcdefd1a4326..a09d87f7c096672a1b85d56444ee6343b429e272 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -2,7 +2,7 @@ use crate::headless_project::HeadlessProject; use client::{Client, UserStore}; use clock::FakeSystemClock; use fs::{FakeFs, Fs}; -use gpui::{Context, Model, TestAppContext}; +use gpui::{Context, Model, SemanticVersion, TestAppContext}; use http_client::{BlockedHttpClient, FakeHttpClient}; use language::{ language_settings::{language_settings, AllLanguageSettings}, @@ -1184,6 +1184,9 @@ pub async fn init_test( server_cx: &mut TestAppContext, ) -> (Model, Model) { let server_fs = server_fs.clone(); + cx.update(|cx| { + release_channel::init(SemanticVersion::default(), cx); + }); init_logger(); let (opts, ssh_server_client) = SshRemoteClient::fake_server(cx, server_cx); diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 6486302152387b6ef5827890d87873a37fe520f5..04d47aec6eac6f405fa110fe707a39d15a229cf9 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -50,7 +50,6 @@ parking_lot.workspace = true postage.workspace = true project.workspace = true task.workspace = true -release_channel.workspace = true remote.workspace = true schemars.workspace = true serde.workspace = true diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 24c681083b12cab06b7dc8a38d4e3880f343c7d4..18b9994f3d14969d261f037c3664963e91f9251e 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -63,8 +63,7 @@ use postage::stream::Stream; use project::{ DirectoryLister, Project, ProjectEntryId, ProjectPath, ResolvedPath, Worktree, WorktreeId, }; -use release_channel::ReleaseChannel; -use remote::{SshClientDelegate, SshConnectionOptions}; +use remote::{ssh_session::ConnectionIdentifier, SshClientDelegate, SshConnectionOptions}; use serde::Deserialize; use session::AppSession; use settings::Settings; @@ -5494,26 +5493,14 @@ pub fn open_ssh_project( paths: Vec, cx: &mut AppContext, ) -> Task> { - let release_channel = ReleaseChannel::global(cx); - cx.spawn(|mut cx| async move { let (serialized_ssh_project, workspace_id, serialized_workspace) = serialize_ssh_project(connection_options.clone(), paths.clone(), &cx).await?; - let identifier_prefix = match release_channel { - ReleaseChannel::Stable => None, - _ => Some(format!("{}-", release_channel.dev_name())), - }; - let unique_identifier = format!( - "{}workspace-{}", - identifier_prefix.unwrap_or_default(), - workspace_id.0 - ); - let session = match cx .update(|cx| { remote::SshRemoteClient::new( - unique_identifier, + ConnectionIdentifier::Workspace(workspace_id.0), connection_options, cancel_rx, delegate,