Cargo.lock 🔗
@@ -17658,7 +17658,11 @@ dependencies = [
"pretty_assertions",
"project",
"regex",
+ "release_channel",
+ "remote",
+ "rpc",
"schemars",
+ "semver",
"serde",
"serde_json",
"settings",
Sergei Shulepov created
When opening a remote session, sometimes you get a message:
/bin/bash: line 1: cd: /Users/pep: No such file or directory
which suggests that that the local home dir (/Users/pep) is used for the
remote terminal session, where it should be something like /home/ubuntu.
Release Notes:
- Fixed remote terminals incorrectly trying to change to a local home
directory.
Cargo.lock | 4 +
crates/terminal_view/Cargo.toml | 4 +
crates/terminal_view/src/terminal_view.rs | 85 ++++++++++++++++++++++++
3 files changed, 91 insertions(+), 2 deletions(-)
@@ -17658,7 +17658,11 @@ dependencies = [
"pretty_assertions",
"project",
"regex",
+ "release_channel",
+ "remote",
+ "rpc",
"schemars",
+ "semver",
"serde",
"serde_json",
"settings",
@@ -51,6 +51,10 @@ zed_actions.workspace = true
editor = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
+remote = { workspace = true, features = ["test-support"] }
+release_channel.workspace = true
+rpc = { workspace = true, features = ["test-support"] }
+semver.workspace = true
terminal = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }
@@ -1971,8 +1971,9 @@ impl SearchableItem for TerminalView {
}
/// Gets the working directory for the given workspace, respecting the user's settings.
-/// Falls back to home directory when no project directory is available.
+/// Falls back to the local home directory only for local workspaces.
pub(crate) fn default_working_directory(workspace: &Workspace, cx: &App) -> Option<PathBuf> {
+ let should_fallback_to_local_home = workspace.project().read(cx).is_local();
let directory = match &TerminalSettings::get_global(cx).working_directory {
WorkingDirectory::CurrentFileDirectory => workspace
.project()
@@ -1987,7 +1988,12 @@ pub(crate) fn default_working_directory(workspace: &Workspace, cx: &App) -> Opti
.map(|dir| Path::new(&dir.to_string()).to_path_buf())
.filter(|dir| dir.is_dir()),
};
- directory.or_else(dirs::home_dir)
+
+ if should_fallback_to_local_home {
+ directory.or_else(dirs::home_dir)
+ } else {
+ directory
+ }
}
fn current_project_directory(workspace: &Workspace, cx: &App) -> Option<PathBuf> {
@@ -2017,6 +2023,7 @@ mod tests {
use super::*;
use gpui::TestAppContext;
use project::{Entry, Project, ProjectPath, Worktree};
+ use remote::RemoteClient;
use std::path::{Path, PathBuf};
use util::paths::PathStyle;
use util::rel_path::RelPath;
@@ -2079,6 +2086,22 @@ mod tests {
});
}
+ #[gpui::test]
+ async fn remote_no_worktree_uses_remote_shell_default_cwd(
+ cx: &mut TestAppContext,
+ server_cx: &mut TestAppContext,
+ ) {
+ let (_project, workspace) = init_remote_test(cx, server_cx).await;
+
+ cx.read(|cx| {
+ let workspace = workspace.read(cx);
+
+ assert!(workspace.project().read(cx).is_remote());
+ assert!(workspace.worktrees(cx).next().is_none());
+ assert_eq!(default_working_directory(workspace, cx), None);
+ });
+ }
+
// No active entry, but a worktree, worktree is a file -> parent directory
#[gpui::test]
async fn no_active_entry_worktree_is_file(cx: &mut TestAppContext) {
@@ -2237,6 +2260,64 @@ mod tests {
(project, workspace, window_handle)
}
+ async fn init_remote_test(
+ cx: &mut TestAppContext,
+ server_cx: &mut TestAppContext,
+ ) -> (Entity<Project>, Entity<Workspace>) {
+ cx.update(|cx| {
+ release_channel::init(semver::Version::new(0, 0, 0), cx);
+ });
+ server_cx.update(|cx| {
+ release_channel::init(semver::Version::new(0, 0, 0), cx);
+ });
+
+ let params = cx.update(AppState::test);
+ let (opts, server_session, connect_guard) = RemoteClient::fake_server(cx, server_cx);
+ let ping_handler = server_cx.new(|_| ());
+ server_session.add_request_handler::<rpc::proto::Ping, _, _, _>(
+ ping_handler.downgrade(),
+ |_entity, _envelope, _cx| async { Ok(rpc::proto::Ack {}) },
+ );
+ drop(connect_guard);
+
+ let remote_client = RemoteClient::connect_mock(opts, cx).await;
+ let project = cx.update(|cx| {
+ Project::remote(
+ remote_client,
+ params.client.clone(),
+ params.node_runtime.clone(),
+ params.user_store.clone(),
+ params.languages.clone(),
+ params.fs.clone(),
+ false,
+ cx,
+ )
+ });
+
+ let window_handle = cx.add_window({
+ let params = params.clone();
+ let project_for_workspace = project.clone();
+ move |window, cx| {
+ window.activate_window();
+ let workspace = cx.new(|cx| {
+ Workspace::new(
+ None,
+ project_for_workspace.clone(),
+ params.clone(),
+ window,
+ cx,
+ )
+ });
+ MultiWorkspace::new(workspace, window, cx)
+ }
+ });
+ let workspace = window_handle
+ .read_with(cx, |mw, _| mw.workspace().clone())
+ .unwrap();
+
+ (project, workspace)
+ }
+
/// Creates a file in the given worktree and returns its entry.
async fn create_file_in_worktree(
worktree: Entity<Worktree>,