diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 55f440852ada15505831c78035d9362c91b4a204..068fb8d71fa883e9d2b518c7d19adacea74fadcb 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -3403,8 +3403,7 @@ impl ProjectPanel { _: &mut Window, cx: &mut Context, ) { - if let Some((worktree, entry)) = self.selected_sub_entry(cx) { - let path = worktree.read(cx).absolutize(&entry.path); + if let Some(path) = self.reveal_in_file_manager_path(cx) { self.project .update(cx, |project, cx| project.reveal_path(&path, cx)); } @@ -3761,6 +3760,20 @@ impl ProjectPanel { } Some((worktree, entry)) } + + fn reveal_in_file_manager_path(&self, cx: &App) -> Option { + if let Some((worktree, entry)) = self.selected_sub_entry(cx) { + return Some(worktree.read(cx).absolutize(&entry.path)); + } + + let root_entry_id = self.state.last_worktree_root_id?; + let project = self.project.read(cx); + let worktree = project.worktree_for_entry(root_entry_id, cx)?; + let worktree = worktree.read(cx); + let root_entry = worktree.entry_for_id(root_entry_id)?; + Some(worktree.absolutize(&root_entry.path)) + } + fn selected_entry_handle<'a>( &self, cx: &'a App, diff --git a/crates/project_panel/src/project_panel_tests.rs b/crates/project_panel/src/project_panel_tests.rs index 64e96fee700aea8277fe1b69121abf71599c4d30..720ac04fdd2a656a32668add23e7af021a71ef00 100644 --- a/crates/project_panel/src/project_panel_tests.rs +++ b/crates/project_panel/src/project_panel_tests.rs @@ -8670,6 +8670,55 @@ async fn test_compare_files_context_menu(cx: &mut gpui::TestAppContext) { } } +#[gpui::test] +async fn test_reveal_in_file_manager_path_falls_back_to_worktree_root( + cx: &mut gpui::TestAppContext, +) { + init_test(cx); + + let fs = FakeFs::new(cx.executor()); + fs.insert_tree( + "/root", + json!({ + "file.txt": "content", + "dir": {}, + }), + ) + .await; + + let project = Project::test(fs.clone(), ["/root".as_ref()], cx).await; + let window = cx.add_window(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx)); + let workspace = window + .read_with(cx, |mw, _| mw.workspace().clone()) + .unwrap(); + let cx = &mut VisualTestContext::from_window(window.into(), cx); + let panel = workspace.update_in(cx, ProjectPanel::new); + cx.run_until_parked(); + + select_path(&panel, "root/file.txt", cx); + let selected_reveal_path = panel + .update(cx, |panel, cx| panel.reveal_in_file_manager_path(cx)) + .expect("selected entry should produce a reveal path"); + assert!( + selected_reveal_path.ends_with(Path::new("file.txt")), + "Expected selected file path, got {:?}", + selected_reveal_path + ); + + panel.update(cx, |panel, _| { + panel.selection = None; + panel.marked_entries.clear(); + }); + let fallback_reveal_path = panel + .update(cx, |panel, cx| panel.reveal_in_file_manager_path(cx)) + .expect("project root should be used when selection is empty"); + assert!( + fallback_reveal_path.ends_with(Path::new("root")), + "Expected worktree root path, got {:?}", + fallback_reveal_path + ); +} + #[gpui::test] async fn test_hide_hidden_entries(cx: &mut gpui::TestAppContext) { init_test(cx);