ssh remoting: Fix wrong working directory for SSH terminals (#19672)

Before this change, we would save the working directory *on the client*
of each shell that was running in a terminal.

While it's technically right, it's wrong in all of these cases where
`working_directory` was used:

- in inline assistant
- when resolving file paths in the terminal output
- when serializing the current working dir and deserializing it on
restart

Release Notes:

- Fixed terminals opened on remote hosts failing to deserialize with an
error message after restarting Zed.
This commit is contained in:
Thorsten Ball 2024-10-24 13:52:26 +02:00 committed by GitHub
parent 4214ed927f
commit efc4d3efdf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 7 deletions

View file

@ -240,6 +240,7 @@ impl Project {
settings.cursor_shape.unwrap_or_default(),
settings.alternate_scroll,
settings.max_scroll_history_lines,
ssh_details.is_some(),
window,
completion_tx,
cx,

View file

@ -330,6 +330,7 @@ impl TerminalBuilder {
cursor_shape: CursorShape,
alternate_scroll: AlternateScroll,
max_scroll_history_lines: Option<usize>,
is_ssh_terminal: bool,
window: AnyWindowHandle,
completion_tx: Sender<()>,
cx: &AppContext,
@ -469,6 +470,7 @@ impl TerminalBuilder {
url_regex: RegexSearch::new(URL_REGEX).unwrap(),
word_regex: RegexSearch::new(WORD_REGEX).unwrap(),
vi_mode_enabled: false,
is_ssh_terminal,
};
Ok(TerminalBuilder {
@ -626,6 +628,7 @@ pub struct Terminal {
word_regex: RegexSearch,
task: Option<TaskState>,
vi_mode_enabled: bool,
is_ssh_terminal: bool,
}
pub struct TaskState {
@ -734,10 +737,6 @@ impl Terminal {
self.selection_phase == SelectionPhase::Selecting
}
pub fn get_cwd(&self) -> Option<PathBuf> {
self.pty_info.current.as_ref().map(|info| info.cwd.clone())
}
///Takes events from Alacritty and translates them to behavior on this view
fn process_terminal_event(
&mut self,
@ -951,7 +950,7 @@ impl Terminal {
} else {
MaybeNavigationTarget::PathLike(PathLikeTarget {
maybe_path: maybe_url_or_path,
terminal_dir: self.get_cwd(),
terminal_dir: self.working_directory(),
})
};
cx.emit(Event::Open(target));
@ -1006,7 +1005,7 @@ impl Terminal {
} else {
MaybeNavigationTarget::PathLike(PathLikeTarget {
maybe_path: word,
terminal_dir: self.get_cwd(),
terminal_dir: self.working_directory(),
})
};
cx.emit(Event::NewNavigationTarget(Some(navigation_target)));
@ -1636,6 +1635,23 @@ impl Terminal {
}
pub fn working_directory(&self) -> Option<PathBuf> {
if self.is_ssh_terminal {
// We can't yet reliably detect the working directory of a shell on the
// SSH host. Until we can do that, it doesn't make sense to display
// the working directory on the client and persist that.
None
} else {
self.client_side_working_directory()
}
}
/// Returns the working directory of the process that's connected to the PTY.
/// That means it returns the working directory of the local shell or program
/// that's running inside the terminal.
///
/// This does *not* return the working directory of the shell that runs on the
/// remote host, in case Zed is connected to a remote host.
fn client_side_working_directory(&self) -> Option<PathBuf> {
self.pty_info
.current
.as_ref()

View file

@ -1192,7 +1192,7 @@ impl SerializableItem for TerminalView {
return None;
}
if let Some((cwd, workspace_id)) = terminal.get_cwd().zip(self.workspace_id) {
if let Some((cwd, workspace_id)) = terminal.working_directory().zip(self.workspace_id) {
Some(cx.background_executor().spawn(async move {
TERMINAL_DB
.save_working_directory(item_id, workspace_id, cwd)