diff --git a/Cargo.lock b/Cargo.lock index 77ccfe789f121f9358acc79507f4d6419b37ed20..2157d065f2c1e0bf13fb8d402ea0f2970579d1bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17658,7 +17658,11 @@ dependencies = [ "pretty_assertions", "project", "regex", + "release_channel", + "remote", + "rpc", "schemars", + "semver", "serde", "serde_json", "settings", diff --git a/crates/terminal_view/Cargo.toml b/crates/terminal_view/Cargo.toml index f74d8b83883a1186d91855429c40f375bfa22526..9da4c5ec6e1cf5412a3e4d1f3a677551dd5b2688 100644 --- a/crates/terminal_view/Cargo.toml +++ b/crates/terminal_view/Cargo.toml @@ -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"] } diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 636ce30e6e243f49767fbe3c248319a8bc94b9f7..5c772c18f19fb12d77c2100d602aab08e635b1d2 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -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 { + 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 { @@ -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, Entity) { + 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::( + 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,