diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index fac8d33347..d09ef9bd8f 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -95,7 +95,10 @@ use task_store::TaskStore; use terminals::Terminals; use text::{Anchor, BufferId}; use toolchain_store::EmptyToolchainStore; -use util::{paths::compare_paths, ResultExt as _}; +use util::{ + paths::{compare_paths, SanitizedPath}, + ResultExt as _, +}; use worktree::{CreatedEntry, Snapshot, Traversal}; use worktree_store::{WorktreeStore, WorktreeStoreEvent}; @@ -1484,22 +1487,37 @@ impl Project { .and_then(|worktree| worktree.read(cx).status_for_file(&project_path.path)) } - pub fn visibility_for_paths(&self, paths: &[PathBuf], cx: &App) -> Option { + pub fn visibility_for_paths( + &self, + paths: &[PathBuf], + metadatas: &[Metadata], + exclude_sub_dirs: bool, + cx: &App, + ) -> Option { paths .iter() - .map(|path| self.visibility_for_path(path, cx)) + .zip(metadatas) + .map(|(path, metadata)| self.visibility_for_path(path, metadata, exclude_sub_dirs, cx)) .max() .flatten() } - pub fn visibility_for_path(&self, path: &Path, cx: &App) -> Option { + pub fn visibility_for_path( + &self, + path: &Path, + metadata: &Metadata, + exclude_sub_dirs: bool, + cx: &App, + ) -> Option { + let sanitized_path = SanitizedPath::from(path); + let path = sanitized_path.as_path(); self.worktrees(cx) .filter_map(|worktree| { let worktree = worktree.read(cx); - worktree - .as_local()? - .contains_abs_path(path) - .then(|| worktree.is_visible()) + let abs_path = worktree.as_local()?.abs_path(); + let contains = path == abs_path + || (path.starts_with(abs_path) && (!exclude_sub_dirs || !metadata.is_dir)); + contains.then(|| worktree.is_visible()) }) .max() } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 2ad9cf1c4d..53bd58596c 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -5958,7 +5958,6 @@ pub struct OpenOptions { pub replace_window: Option>, pub env: Option>, } - #[allow(clippy::type_complexity)] pub fn open_paths( abs_paths: &[PathBuf], @@ -5976,58 +5975,65 @@ pub fn open_paths( let mut best_match = None; let mut open_visible = OpenVisible::All; - if open_options.open_new_workspace != Some(true) { - for window in local_workspace_windows(cx) { - if let Ok(workspace) = window.read(cx) { - let m = workspace - .project - .read(cx) - .visibility_for_paths(&abs_paths, cx); - if m > best_match { - existing = Some(window); - best_match = m; - } else if best_match.is_none() && open_options.open_new_workspace == Some(false) { - existing = Some(window) - } - } - } - } - cx.spawn(move |mut cx| async move { - if open_options.open_new_workspace.is_none() && existing.is_none() { - let all_files = abs_paths.iter().map(|path| app_state.fs.metadata(path)); - if futures::future::join_all(all_files) + if open_options.open_new_workspace != Some(true) { + let all_paths = abs_paths.iter().map(|path| app_state.fs.metadata(path)); + let all_metadatas = futures::future::join_all(all_paths) .await .into_iter() .filter_map(|result| result.ok().flatten()) - .all(|file| !file.is_dir) - { - cx.update(|cx| { - if let Some(window) = cx - .active_window() - .and_then(|window| window.downcast::()) - { - if let Ok(workspace) = window.read(cx) { - let project = workspace.project().read(cx); - if project.is_local() && !project.is_via_collab() { + .collect::>(); + + cx.update(|cx| { + for window in local_workspace_windows(&cx) { + if let Ok(workspace) = window.read(&cx) { + let m = workspace.project.read(&cx).visibility_for_paths( + &abs_paths, + &all_metadatas, + open_options.open_new_workspace == None, + cx, + ); + if m > best_match { + existing = Some(window); + best_match = m; + } else if best_match.is_none() + && open_options.open_new_workspace == Some(false) + { + existing = Some(window) + } + } + } + })?; + + if open_options.open_new_workspace.is_none() && existing.is_none() { + if all_metadatas.iter().all(|file| !file.is_dir) { + cx.update(|cx| { + if let Some(window) = cx + .active_window() + .and_then(|window| window.downcast::()) + { + if let Ok(workspace) = window.read(cx) { + let project = workspace.project().read(cx); + if project.is_local() && !project.is_via_collab() { + existing = Some(window); + open_visible = OpenVisible::None; + return; + } + } + } + for window in local_workspace_windows(cx) { + if let Ok(workspace) = window.read(cx) { + let project = workspace.project().read(cx); + if project.is_via_collab() { + continue; + } existing = Some(window); open_visible = OpenVisible::None; - return; + break; } } - } - for window in local_workspace_windows(cx) { - if let Ok(workspace) = window.read(cx) { - let project = workspace.project().read(cx); - if project.is_via_collab() { - continue; - } - existing = Some(window); - open_visible = OpenVisible::None; - break; - } - } - })?; + })?; + } } } diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 07f77283db..88c61c9af6 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -1335,11 +1335,6 @@ impl LocalWorktree { &self.fs } - pub fn contains_abs_path(&self, path: &Path) -> bool { - let path = SanitizedPath::from(path); - path.starts_with(&self.abs_path) - } - pub fn is_path_private(&self, path: &Path) -> bool { !self.share_private_files && self.settings.is_path_private(path) }