remote: Check if remote can --exec, fall back to spawning shell otherwise (#40112)
Bonus: fix passing env vars to the proxy server in WSL setting. Closes #39710 Supersedes #39893 Release Notes: - N/A
This commit is contained in:
@@ -38,12 +38,14 @@ impl From<settings::WslConnection> for WslConnectionOptions {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WslRemoteConnection {
|
||||
remote_binary_path: Option<Arc<RelPath>>,
|
||||
platform: RemotePlatform,
|
||||
shell: String,
|
||||
default_system_shell: String,
|
||||
connection_options: WslConnectionOptions,
|
||||
can_exec: bool,
|
||||
}
|
||||
|
||||
impl WslRemoteConnection {
|
||||
@@ -71,18 +73,48 @@ impl WslRemoteConnection {
|
||||
platform: RemotePlatform { os: "", arch: "" },
|
||||
shell: String::new(),
|
||||
default_system_shell: String::from("/bin/sh"),
|
||||
can_exec: true,
|
||||
};
|
||||
delegate.set_status(Some("Detecting WSL environment"), cx);
|
||||
this.can_exec = this.detect_can_exec().await?;
|
||||
this.platform = this.detect_platform().await?;
|
||||
this.shell = this.detect_shell().await?;
|
||||
this.remote_binary_path = Some(
|
||||
this.ensure_server_binary(&delegate, release_channel, version, commit, cx)
|
||||
.await?,
|
||||
);
|
||||
log::debug!("Detected WSL environment: {this:#?}");
|
||||
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
async fn detect_can_exec(&self) -> Result<bool> {
|
||||
let options = &self.connection_options;
|
||||
let program = "uname";
|
||||
let args = &["-m"];
|
||||
let output = wsl_command_impl(options, program, args, true)
|
||||
.output()
|
||||
.await?;
|
||||
|
||||
if !output.status.success() {
|
||||
let output = wsl_command_impl(options, program, args, false)
|
||||
.output()
|
||||
.await?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(anyhow!(
|
||||
"Command '{}' failed: {}",
|
||||
program,
|
||||
String::from_utf8_lossy(&output.stderr).trim()
|
||||
));
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
async fn detect_platform(&self) -> Result<RemotePlatform> {
|
||||
let arch_str = self.run_wsl_command("uname", &["-m"]).await?;
|
||||
let arch_str = arch_str.trim().to_string();
|
||||
@@ -103,15 +135,15 @@ impl WslRemoteConnection {
|
||||
}
|
||||
|
||||
async fn windows_path_to_wsl_path(&self, source: &Path) -> Result<String> {
|
||||
windows_path_to_wsl_path_impl(&self.connection_options, source).await
|
||||
windows_path_to_wsl_path_impl(&self.connection_options, source, self.can_exec).await
|
||||
}
|
||||
|
||||
fn wsl_command(&self, program: &str, args: &[impl AsRef<OsStr>]) -> process::Command {
|
||||
wsl_command_impl(&self.connection_options, program, args)
|
||||
wsl_command_impl(&self.connection_options, program, args, self.can_exec)
|
||||
}
|
||||
|
||||
async fn run_wsl_command(&self, program: &str, args: &[&str]) -> Result<String> {
|
||||
run_wsl_command_impl(&self.connection_options, program, args).await
|
||||
run_wsl_command_impl(&self.connection_options, program, args, self.can_exec).await
|
||||
}
|
||||
|
||||
async fn ensure_server_binary(
|
||||
@@ -296,7 +328,10 @@ impl RemoteConnection for WslRemoteConnection {
|
||||
let mut proxy_args = vec![];
|
||||
for env_var in ["RUST_LOG", "RUST_BACKTRACE", "ZED_GENERATE_MINIDUMPS"] {
|
||||
if let Some(value) = std::env::var(env_var).ok() {
|
||||
proxy_args.push(format!("{}='{}'", env_var, value));
|
||||
// We don't quote the value here as it seems excessive and may result in invalid envs for the
|
||||
// proxy server. For example, `RUST_LOG='debug'` will result in a warning "invalid logging spec 'debug'', ignoring it"
|
||||
// in the proxy server. Therefore, we pass the env vars as is.
|
||||
proxy_args.push(format!("{}={}", env_var, value));
|
||||
}
|
||||
}
|
||||
proxy_args.push(remote_binary_path.display(PathStyle::Posix).into_owned());
|
||||
@@ -335,19 +370,25 @@ impl RemoteConnection for WslRemoteConnection {
|
||||
) -> Task<Result<()>> {
|
||||
cx.background_spawn({
|
||||
let options = self.connection_options.clone();
|
||||
let can_exec = self.can_exec;
|
||||
async move {
|
||||
let wsl_src = windows_path_to_wsl_path_impl(&options, &src_path).await?;
|
||||
let wsl_src = windows_path_to_wsl_path_impl(&options, &src_path, can_exec).await?;
|
||||
|
||||
run_wsl_command_impl(&options, "cp", &["-r", &wsl_src, &dest_path.to_string()])
|
||||
.await
|
||||
.map_err(|e| {
|
||||
anyhow!(
|
||||
"failed to upload directory {} -> {}: {}",
|
||||
src_path.display(),
|
||||
dest_path.to_string(),
|
||||
e
|
||||
)
|
||||
})?;
|
||||
run_wsl_command_impl(
|
||||
&options,
|
||||
"cp",
|
||||
&["-r", &wsl_src, &dest_path.to_string()],
|
||||
can_exec,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
anyhow!(
|
||||
"failed to upload directory {} -> {}: {}",
|
||||
src_path.display(),
|
||||
dest_path.to_string(),
|
||||
e
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -472,17 +513,21 @@ async fn sanitize_path(path: &Path) -> Result<String> {
|
||||
async fn windows_path_to_wsl_path_impl(
|
||||
options: &WslConnectionOptions,
|
||||
source: &Path,
|
||||
exec: bool,
|
||||
) -> Result<String> {
|
||||
let source = sanitize_path(source).await?;
|
||||
run_wsl_command_impl(options, "wslpath", &["-u", &source]).await
|
||||
run_wsl_command_impl(options, "wslpath", &["-u", &source], exec).await
|
||||
}
|
||||
|
||||
async fn run_wsl_command_impl(
|
||||
options: &WslConnectionOptions,
|
||||
program: &str,
|
||||
args: &[&str],
|
||||
exec: bool,
|
||||
) -> Result<String> {
|
||||
let output = wsl_command_impl(options, program, args).output().await?;
|
||||
let output = wsl_command_impl(options, program, args, exec)
|
||||
.output()
|
||||
.await?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(anyhow!(
|
||||
@@ -502,6 +547,7 @@ fn wsl_command_impl(
|
||||
options: &WslConnectionOptions,
|
||||
program: &str,
|
||||
args: &[impl AsRef<OsStr>],
|
||||
exec: bool,
|
||||
) -> process::Command {
|
||||
let mut command = util::command::new_smol_command("wsl.exe");
|
||||
|
||||
@@ -516,10 +562,13 @@ fn wsl_command_impl(
|
||||
.arg("--distribution")
|
||||
.arg(&options.distro_name)
|
||||
.arg("--cd")
|
||||
.arg("~")
|
||||
.arg("--exec")
|
||||
.arg(program)
|
||||
.args(args);
|
||||
.arg("~");
|
||||
|
||||
if exec {
|
||||
command.arg("--exec");
|
||||
}
|
||||
|
||||
command.arg(program).args(args);
|
||||
|
||||
log::debug!("wsl {:?}", command);
|
||||
command
|
||||
|
||||
Reference in New Issue
Block a user