SSH remoting: better error message for projects (#19320)

Conrad Irwin created

Before this, if no project paths were opened you were in a wierd UI
state where
most things didn't work because the project was ssh, but no
files/folders were open.

Release Notes:

- Fixed error handling when no project paths could be opened

Change summary

crates/remote/src/ssh_session.rs  | 29 ++++++++++++++++-------------
crates/workspace/src/workspace.rs |  6 ++++++
2 files changed, 22 insertions(+), 13 deletions(-)

Detailed changes

crates/remote/src/ssh_session.rs 🔗

@@ -979,16 +979,9 @@ impl SshRemoteClient {
             SshRemoteConnection::new(connection_options, delegate.clone(), cx).await?;
 
         let platform = ssh_connection.query_platform().await?;
-        let (local_binary_path, version) = delegate.get_server_binary(platform, cx).await??;
         let remote_binary_path = delegate.remote_server_binary_path(platform, cx)?;
         ssh_connection
-            .ensure_server_binary(
-                &delegate,
-                &local_binary_path,
-                &remote_binary_path,
-                version,
-                cx,
-            )
+            .ensure_server_binary(&delegate, &remote_binary_path, platform, cx)
             .await?;
 
         let socket = ssh_connection.socket.clone();
@@ -1252,11 +1245,19 @@ impl SshRemoteConnection {
     async fn ensure_server_binary(
         &self,
         delegate: &Arc<dyn SshClientDelegate>,
-        src_path: &Path,
         dst_path: &Path,
-        version: SemanticVersion,
+        platform: SshPlatform,
         cx: &mut AsyncAppContext,
     ) -> Result<()> {
+        if std::env::var("ZED_USE_CACHED_REMOTE_SERVER").is_ok() {
+            if let Ok(installed_version) =
+                run_cmd(self.socket.ssh_command(dst_path).arg("version")).await
+            {
+                log::info!("using cached server binary version {}", installed_version);
+                return Ok(());
+            }
+        }
+
         let mut dst_path_gz = dst_path.to_path_buf();
         dst_path_gz.set_extension("gz");
 
@@ -1264,8 +1265,10 @@ impl SshRemoteConnection {
             run_cmd(self.socket.ssh_command("mkdir").arg("-p").arg(parent)).await?;
         }
 
+        let (src_path, version) = delegate.get_server_binary(platform, cx).await??;
+
         let mut server_binary_exists = false;
-        if cfg!(not(debug_assertions)) {
+        if !server_binary_exists && cfg!(not(debug_assertions)) {
             if let Ok(installed_version) =
                 run_cmd(self.socket.ssh_command(dst_path).arg("version")).await
             {
@@ -1280,14 +1283,14 @@ impl SshRemoteConnection {
             return Ok(());
         }
 
-        let src_stat = fs::metadata(src_path).await?;
+        let src_stat = fs::metadata(&src_path).await?;
         let size = src_stat.len();
         let server_mode = 0o755;
 
         let t0 = Instant::now();
         delegate.set_status(Some("uploading remote development server"), cx);
         log::info!("uploading remote development server ({}kb)", size / 1024);
-        self.upload_file(src_path, &dst_path_gz)
+        self.upload_file(&src_path, &dst_path_gz)
             .await
             .context("failed to upload server binary")?;
         log::info!("uploaded remote development server in {:?}", t0.elapsed());

crates/workspace/src/workspace.rs 🔗

@@ -5568,6 +5568,12 @@ pub fn open_ssh_project(
             };
         }
 
+        if project_paths_to_open.is_empty() {
+            return Err(project_path_errors
+                .pop()
+                .unwrap_or_else(|| anyhow!("no paths given")));
+        }
+
         cx.update_window(window.into(), |_, cx| {
             cx.replace_root_view(|cx| {
                 let mut workspace =