remote: Recognize WSL interop to open browser for codex web login (#44136)

Closes #41521

Release Notes:

- Fixed codex web login not working on wsl remotes if no browser is
installed

Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
This commit is contained in:
Lukas Wirth
2025-12-04 14:42:26 +00:00
committed by GitHub
co-authored by Ben Brandt
parent c978db8626
commit a33e881906
9 changed files with 79 additions and 17 deletions
+25 -5
View File
@@ -328,8 +328,15 @@ impl RemoteClient {
let (incoming_tx, incoming_rx) = mpsc::unbounded::<Envelope>();
let (connection_activity_tx, connection_activity_rx) = mpsc::channel::<()>(1);
let client =
cx.update(|cx| ChannelClient::new(incoming_rx, outgoing_tx, cx, "client"))?;
let client = cx.update(|cx| {
ChannelClient::new(
incoming_rx,
outgoing_tx,
cx,
"client",
remote_connection.has_wsl_interop(),
)
})?;
let path_style = remote_connection.path_style();
let this = cx.new(|_| Self {
@@ -420,8 +427,9 @@ impl RemoteClient {
outgoing_tx: mpsc::UnboundedSender<Envelope>,
cx: &App,
name: &'static str,
has_wsl_interop: bool,
) -> AnyProtoClient {
ChannelClient::new(incoming_rx, outgoing_tx, cx, name).into()
ChannelClient::new(incoming_rx, outgoing_tx, cx, name, has_wsl_interop).into()
}
pub fn shutdown_processes<T: RequestMessage>(
@@ -921,8 +929,8 @@ impl RemoteClient {
});
let (outgoing_tx, _) = mpsc::unbounded::<Envelope>();
let (_, incoming_rx) = mpsc::unbounded::<Envelope>();
let server_client =
server_cx.update(|cx| ChannelClient::new(incoming_rx, outgoing_tx, cx, "fake-server"));
let server_client = server_cx
.update(|cx| ChannelClient::new(incoming_rx, outgoing_tx, cx, "fake-server", false));
let connection: Arc<dyn RemoteConnection> = Arc::new(fake::FakeRemoteConnection {
connection_options: opts.clone(),
server_cx: fake::SendableCx::new(server_cx),
@@ -1140,6 +1148,7 @@ pub trait RemoteConnection: Send + Sync {
fn path_style(&self) -> PathStyle;
fn shell(&self) -> String;
fn default_system_shell(&self) -> String;
fn has_wsl_interop(&self) -> bool;
#[cfg(any(test, feature = "test-support"))]
fn simulate_disconnect(&self, _: &AsyncApp) {}
@@ -1188,6 +1197,7 @@ struct ChannelClient {
name: &'static str,
task: Mutex<Task<Result<()>>>,
remote_started: Signal<()>,
has_wsl_interop: bool,
}
impl ChannelClient {
@@ -1196,6 +1206,7 @@ impl ChannelClient {
outgoing_tx: mpsc::UnboundedSender<Envelope>,
cx: &App,
name: &'static str,
has_wsl_interop: bool,
) -> Arc<Self> {
Arc::new_cyclic(|this| Self {
outgoing_tx: Mutex::new(outgoing_tx),
@@ -1211,6 +1222,7 @@ impl ChannelClient {
&cx.to_async(),
)),
remote_started: Signal::new(cx),
has_wsl_interop,
})
}
@@ -1489,6 +1501,10 @@ impl ProtoClient for ChannelClient {
fn is_via_collab(&self) -> bool {
false
}
fn has_wsl_interop(&self) -> bool {
self.has_wsl_interop
}
}
#[cfg(any(test, feature = "test-support"))]
@@ -1652,6 +1668,10 @@ mod fake {
fn default_system_shell(&self) -> String {
"sh".to_owned()
}
fn has_wsl_interop(&self) -> bool {
false
}
}
pub(super) struct Delegate;
+1 -5
View File
@@ -131,11 +131,7 @@ async fn build_remote_server_from_source(
let build_remote_server =
std::env::var("ZED_BUILD_REMOTE_SERVER").unwrap_or("nocompress".into());
if build_remote_server == "false"
|| build_remote_server == "no"
|| build_remote_server == "off"
|| build_remote_server == "0"
{
if let "false" | "no" | "off" | "0" = &*build_remote_server {
return Ok(None);
}
+4
View File
@@ -394,6 +394,10 @@ impl RemoteConnection for SshRemoteConnection {
fn path_style(&self) -> PathStyle {
self.ssh_path_style
}
fn has_wsl_interop(&self) -> bool {
false
}
}
impl SshRemoteConnection {
+24
View File
@@ -47,6 +47,7 @@ pub(crate) struct WslRemoteConnection {
shell: String,
shell_kind: ShellKind,
default_system_shell: String,
has_wsl_interop: bool,
connection_options: WslConnectionOptions,
}
@@ -71,6 +72,7 @@ impl WslRemoteConnection {
shell: String::new(),
shell_kind: ShellKind::Posix,
default_system_shell: String::from("/bin/sh"),
has_wsl_interop: false,
};
delegate.set_status(Some("Detecting WSL environment"), cx);
this.shell = this
@@ -79,6 +81,15 @@ impl WslRemoteConnection {
.context("failed detecting shell")?;
log::info!("Remote shell discovered: {}", this.shell);
this.shell_kind = ShellKind::new(&this.shell, false);
this.has_wsl_interop = this.detect_has_wsl_interop().await.unwrap_or_default();
log::info!(
"Remote has wsl interop {}",
if this.has_wsl_interop {
"enabled"
} else {
"disabled"
}
);
this.platform = this
.detect_platform()
.await
@@ -115,6 +126,14 @@ impl WslRemoteConnection {
.unwrap_or_else(|| "/bin/sh".to_string()))
}
async fn detect_has_wsl_interop(&self) -> Result<bool> {
Ok(self
.run_wsl_command_with_output("cat", &["/proc/sys/fs/binfmt_misc/WSLInterop"])
.await
.inspect_err(|err| log::error!("Failed to detect wsl interop: {err}"))?
.contains("enabled"))
}
async fn windows_path_to_wsl_path(&self, source: &Path) -> Result<String> {
windows_path_to_wsl_path_impl(&self.connection_options, source).await
}
@@ -317,6 +336,7 @@ impl RemoteConnection for WslRemoteConnection {
proxy_args.push(format!("{}={}", env_var, value));
}
}
proxy_args.push(remote_binary_path.display(PathStyle::Posix).into_owned());
proxy_args.push("proxy".to_owned());
proxy_args.push("--identifier".to_owned());
@@ -489,6 +509,10 @@ impl RemoteConnection for WslRemoteConnection {
fn default_system_shell(&self) -> String {
self.default_system_shell.clone()
}
fn has_wsl_interop(&self) -> bool {
self.has_wsl_interop
}
}
/// `wslpath` is a executable available in WSL, it's a linux binary.