Allow passing args to ssh (#19336)

This is useful for passing a custom identity file, jump hosts, etc.

Unlike with the v1 feature, we won't support `gh`/`gcloud` ssh wrappers
(yet?). I think the right way of supporting those would be to let
extensions provide remote projects.

Closes #19118

Release Notes:

- SSH remoting: restored ability to set arguments for SSH
This commit is contained in:
Conrad Irwin 2024-10-16 21:09:31 -06:00 committed by GitHub
parent f1d01d59ac
commit 378a2cf9d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 216 additions and 89 deletions

View file

@ -33,7 +33,7 @@ use assets::Assets;
use node_runtime::{NodeBinaryOptions, NodeRuntime};
use parking_lot::Mutex;
use project::project_settings::ProjectSettings;
use recent_projects::open_ssh_project;
use recent_projects::{open_ssh_project, SshSettings};
use release_channel::{AppCommitSha, AppVersion};
use session::{AppSession, Session};
use settings::{
@ -214,6 +214,7 @@ fn init_common(app_state: Arc<AppState>, cx: &mut AppContext) -> Arc<PromptBuild
ThemeRegistry::global(cx),
cx,
);
recent_projects::init(cx);
prompt_builder
}
@ -248,7 +249,6 @@ fn init_ui(
audio::init(Assets, cx);
workspace::init(app_state.clone(), cx);
recent_projects::init(cx);
go_to_line::init(cx);
file_finder::init(cx);
tab_switcher::init(cx);
@ -881,18 +881,25 @@ async fn restore_or_create_workspace(
})?;
task.await?;
}
SerializedWorkspaceLocation::Ssh(ssh_project) => {
SerializedWorkspaceLocation::Ssh(ssh) => {
let args = cx
.update(|cx| {
SshSettings::get_global(cx).args_for(&ssh.host, ssh.port, &ssh.user)
})
.ok()
.flatten();
let connection_options = SshConnectionOptions {
host: ssh_project.host.clone(),
username: ssh_project.user.clone(),
port: ssh_project.port,
args,
host: ssh.host.clone(),
username: ssh.user.clone(),
port: ssh.port,
password: None,
};
let app_state = app_state.clone();
cx.spawn(move |mut cx| async move {
recent_projects::open_ssh_project(
connection_options,
ssh_project.paths.into_iter().map(PathBuf::from).collect(),
ssh.paths.into_iter().map(PathBuf::from).collect(),
app_state,
workspace::OpenOptions::default(),
&mut cx,

View file

@ -16,8 +16,9 @@ use futures::future::join_all;
use futures::{FutureExt, SinkExt, StreamExt};
use gpui::{AppContext, AsyncAppContext, Global, WindowHandle};
use language::{Bias, Point};
use recent_projects::open_ssh_project;
use recent_projects::{open_ssh_project, SshSettings};
use remote::SshConnectionOptions;
use settings::Settings;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;
@ -48,7 +49,7 @@ impl OpenRequest {
} else if let Some(file) = url.strip_prefix("zed://file") {
this.parse_file_path(file)
} else if url.starts_with("ssh://") {
this.parse_ssh_file_path(&url)?
this.parse_ssh_file_path(&url, cx)?
} else if let Some(request_path) = parse_zed_link(&url, cx) {
this.parse_request_path(request_path).log_err();
} else {
@ -65,7 +66,7 @@ impl OpenRequest {
}
}
fn parse_ssh_file_path(&mut self, file: &str) -> Result<()> {
fn parse_ssh_file_path(&mut self, file: &str, cx: &AppContext) -> Result<()> {
let url = url::Url::parse(file)?;
let host = url
.host()
@ -77,11 +78,13 @@ impl OpenRequest {
if !self.open_paths.is_empty() {
return Err(anyhow!("cannot open both local and ssh paths"));
}
let args = SshSettings::get_global(cx).args_for(&host, port, &username);
let connection = SshConnectionOptions {
username,
password,
host,
port,
args,
};
if let Some(ssh_connection) = &self.ssh_connection {
if *ssh_connection != connection {
@ -419,12 +422,25 @@ async fn open_workspaces(
errored = true
}
}
SerializedWorkspaceLocation::Ssh(ssh_project) => {
SerializedWorkspaceLocation::Ssh(ssh) => {
let app_state = app_state.clone();
let args = cx
.update(|cx| {
SshSettings::get_global(cx).args_for(&ssh.host, ssh.port, &ssh.user)
})
.ok()
.flatten();
let connection_options = SshConnectionOptions {
args,
host: ssh.host.clone(),
username: ssh.user.clone(),
port: ssh.port,
password: None,
};
cx.spawn(|mut cx| async move {
open_ssh_project(
ssh_project.connection_options(),
ssh_project.paths.into_iter().map(PathBuf::from).collect(),
connection_options,
ssh.paths.into_iter().map(PathBuf::from).collect(),
app_state,
OpenOptions::default(),
&mut cx,