mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 00:02:23 +00:00
fix(terminal): complete a WSL workspace's panes over its share again (#418)
`wsl_share_cwd` opens with `if !self.host_id.is_local() { return None }`,
which throws away the very case its second branch exists for. A pane in a
WSL workspace is served by the daemon inside the distro, so `set_workspace`
gives it `RemoteTarget::Wsl.host_id()` — never `HostId::LOCAL` — and the
`workspace.target` branch below is unreachable. Tab in those panes fell
back to bash, while the wsl.exe pane in a local workspace (remote context,
no workspace, host LOCAL) kept working.
The locality check belongs to that first branch alone: a `wsl.exe` pane
reaches the distro of whichever machine hosts it, so a remote host's pane
must not read a same-named share here. A `RemoteTarget::Wsl` workspace is
this computer's distro by construction — tty7 reaches those by running
wsl.exe locally, which is why the sidebar labels them "WSL · this computer".
The decision moves into a free `wsl_share_distro`, testable the way
`loopback_plan` is, with all four combinations covered.
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
This commit is contained in:
+81
-16
@@ -615,6 +615,32 @@ fn wsl_share_path(distro: &str, posix: &str) -> Option<std::path::PathBuf> {
|
||||
)))
|
||||
}
|
||||
|
||||
/// The distro whose `\\wsl$` share holds a pane's filesystem, or `None` when
|
||||
/// the pane is not a WSL one and Tab belongs to the shell.
|
||||
///
|
||||
/// The two kinds of WSL pane are told apart by who reports the distro. A pane
|
||||
/// that runs `wsl.exe` is tagged by its remote context, and it reaches the
|
||||
/// distro of whichever machine *hosts* it — so only this machine's panes may
|
||||
/// take the share; a remote host's same-named distro would list the wrong
|
||||
/// files. A pane in a WSL workspace is tagged by its workspace target instead,
|
||||
/// and needs no such check: tty7 reaches those distros by running `wsl.exe`
|
||||
/// here, so the share is this machine's by construction — even though the
|
||||
/// pane's host, being the distro's own server, is not `HostId::LOCAL`.
|
||||
fn wsl_share_distro(
|
||||
remote: Option<&crate::daemon::protocol::RemoteContext>,
|
||||
workspace: Option<&crate::terminal::PaneWorkspace>,
|
||||
host_is_local: bool,
|
||||
) -> Option<String> {
|
||||
match remote {
|
||||
Some(remote) => (remote.kind == crate::daemon::protocol::RemoteKind::Wsl && host_is_local)
|
||||
.then(|| remote.target.clone()),
|
||||
None => match &workspace?.target {
|
||||
crate::core::session::RemoteTarget::Wsl { distro } => Some(distro.clone()),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// The staged image's path as the pane's own filesystem spells it.
|
||||
///
|
||||
/// A WSL pane shares this machine's disk but not its path syntax: an agent in
|
||||
@@ -3644,22 +3670,12 @@ impl TerminalView {
|
||||
/// filesystem is a WSL distro's: the local wsl.exe pane (tagged by its
|
||||
/// remote context) and the WSL-workspace pane (tagged by its workspace
|
||||
/// target) both report a POSIX cwd this process cannot read natively.
|
||||
///
|
||||
/// Only for panes on this machine: a WSL pane owned by a remote host
|
||||
/// reaches its distro through that host, not through a `\\wsl$` share
|
||||
/// here — a same-named local distro would list the wrong machine.
|
||||
fn wsl_share_cwd(&self) -> Option<std::path::PathBuf> {
|
||||
if !self.host_id.is_local() {
|
||||
return None;
|
||||
}
|
||||
let distro = match self.terminal.remote_context() {
|
||||
Some(remote) => (remote.kind == crate::daemon::protocol::RemoteKind::Wsl)
|
||||
.then_some(remote.target)?,
|
||||
None => match &self.workspace.as_ref()?.target {
|
||||
crate::core::session::RemoteTarget::Wsl { distro } => distro.clone(),
|
||||
_ => return None,
|
||||
},
|
||||
};
|
||||
let distro = wsl_share_distro(
|
||||
self.terminal.remote_context().as_ref(),
|
||||
self.workspace.as_ref(),
|
||||
self.host_id.is_local(),
|
||||
)?;
|
||||
let cwd = self.cwd()?;
|
||||
wsl_share_path(&distro, &cwd.to_string_lossy())
|
||||
}
|
||||
@@ -5701,7 +5717,7 @@ mod tests {
|
||||
};
|
||||
use super::{
|
||||
remote_paste_spec, staged_path_for_pane, stages_clipboard_image, staging_cache,
|
||||
staging_dir_is_safe, wsl_path, wsl_share_path,
|
||||
staging_dir_is_safe, wsl_path, wsl_share_distro, wsl_share_path,
|
||||
};
|
||||
use alacritty_terminal::term::TermMode;
|
||||
use gpui::{ClipboardEntry, ClipboardItem, ExternalPaths, Modifiers};
|
||||
@@ -5951,6 +5967,55 @@ mod tests {
|
||||
assert_eq!(remote_paste_user(None, Some(&spec)), Some("me"));
|
||||
}
|
||||
|
||||
fn wsl_context(distro: &str) -> crate::daemon::protocol::RemoteContext {
|
||||
crate::daemon::protocol::RemoteContext {
|
||||
kind: RemoteKind::Wsl,
|
||||
argv: Vec::new(),
|
||||
target: distro.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_wsl_exe_pane_on_this_machine_completes_over_its_own_share() {
|
||||
assert_eq!(
|
||||
wsl_share_distro(Some(&wsl_context("Ubuntu-24.04")), None, true),
|
||||
Some("Ubuntu-24.04".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
/// The same pane on a remote machine reaches that machine's distro, which
|
||||
/// no share here can list.
|
||||
#[test]
|
||||
fn a_remote_hosts_wsl_exe_pane_leaves_tab_to_the_shell() {
|
||||
assert_eq!(
|
||||
wsl_share_distro(Some(&wsl_context("Ubuntu-24.04")), None, false),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
/// A WSL workspace's panes are served by the daemon inside the distro, so
|
||||
/// their host is never `LOCAL` — and the distro is still on this machine.
|
||||
#[test]
|
||||
fn a_wsl_workspace_pane_completes_over_the_share_its_target_names() {
|
||||
let w = ws(
|
||||
RemoteTarget::Wsl {
|
||||
distro: "Ubuntu-24.04".into(),
|
||||
},
|
||||
false,
|
||||
);
|
||||
assert_eq!(
|
||||
wsl_share_distro(None, Some(&w), false),
|
||||
Some("Ubuntu-24.04".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn panes_with_no_distro_of_their_own_have_no_share() {
|
||||
let ssh = ws(RemoteTarget::direct("me", "dev.box", 22), true);
|
||||
assert_eq!(wsl_share_distro(None, Some(&ssh), false), None);
|
||||
assert_eq!(wsl_share_distro(None, None, true), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wsl_and_specless_workspaces_keep_the_local_image_path() {
|
||||
let wsl = ws(
|
||||
|
||||
Reference in New Issue
Block a user