Prevent setting files from showing up in project and contacts panels

Antonio Scandurra created

Change summary

crates/journal/src/journal.rs     |  2 
crates/workspace/src/workspace.rs | 41 +++++++++++++++------
crates/zed/src/zed.rs             | 63 +++++++++++++++++++++++++++++---
3 files changed, 87 insertions(+), 19 deletions(-)

Detailed changes

crates/journal/src/journal.rs 🔗

@@ -49,7 +49,7 @@ pub fn new_journal_entry(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
 
             let opened = workspace
                 .update(&mut cx, |workspace, cx| {
-                    workspace.open_paths(vec![entry_path], cx)
+                    workspace.open_paths(vec![entry_path], true, cx)
                 })
                 .await;
 

crates/workspace/src/workspace.rs 🔗

@@ -885,6 +885,13 @@ impl Workspace {
         self.project.read(cx).worktrees(cx)
     }
 
+    pub fn visible_worktrees<'a>(
+        &self,
+        cx: &'a AppContext,
+    ) -> impl 'a + Iterator<Item = ModelHandle<Worktree>> {
+        self.project.read(cx).visible_worktrees(cx)
+    }
+
     pub fn worktree_scans_complete(&self, cx: &AppContext) -> impl Future<Output = ()> + 'static {
         let futures = self
             .worktrees(cx)
@@ -974,6 +981,7 @@ impl Workspace {
     pub fn open_paths(
         &mut self,
         mut abs_paths: Vec<PathBuf>,
+        visible: bool,
         cx: &mut ViewContext<Self>,
     ) -> Task<Vec<Option<Result<Box<dyn ItemHandle>, Arc<anyhow::Error>>>>> {
         let fs = self.fs.clone();
@@ -984,9 +992,11 @@ impl Workspace {
             let mut entries = Vec::new();
             for path in &abs_paths {
                 entries.push(
-                    this.update(&mut cx, |this, cx| this.project_path_for_path(path, cx))
-                        .await
-                        .ok(),
+                    this.update(&mut cx, |this, cx| {
+                        this.project_path_for_path(path, visible, cx)
+                    })
+                    .await
+                    .log_err(),
                 );
             }
 
@@ -999,7 +1009,7 @@ impl Workspace {
                     cx.spawn(|mut cx| {
                         let fs = fs.clone();
                         async move {
-                            let project_path = project_path?;
+                            let (_worktree, project_path) = project_path?;
                             if fs.is_file(&abs_path).await {
                                 Some(
                                     this.update(&mut cx, |this, cx| {
@@ -1028,7 +1038,7 @@ impl Workspace {
         cx.spawn(|this, mut cx| async move {
             if let Some(paths) = paths.recv().await.flatten() {
                 let results = this
-                    .update(&mut cx, |this, cx| this.open_paths(paths, cx))
+                    .update(&mut cx, |this, cx| this.open_paths(paths, true, cx))
                     .await;
                 for result in results {
                     if let Some(result) = result {
@@ -1063,17 +1073,22 @@ impl Workspace {
     fn project_path_for_path(
         &self,
         abs_path: &Path,
+        visible: bool,
         cx: &mut ViewContext<Self>,
-    ) -> Task<Result<ProjectPath>> {
+    ) -> Task<Result<(ModelHandle<Worktree>, ProjectPath)>> {
         let entry = self.project().update(cx, |project, cx| {
-            project.find_or_create_local_worktree(abs_path, true, cx)
+            project.find_or_create_local_worktree(abs_path, visible, cx)
         });
         cx.spawn(|_, cx| async move {
             let (worktree, path) = entry.await?;
-            Ok(ProjectPath {
-                worktree_id: worktree.read_with(&cx, |t, _| t.id()),
-                path: path.into(),
-            })
+            let worktree_id = worktree.read_with(&cx, |t, _| t.id());
+            Ok((
+                worktree,
+                ProjectPath {
+                    worktree_id,
+                    path: path.into(),
+                },
+            ))
         })
     }
 
@@ -2444,7 +2459,9 @@ pub fn open_paths(
         };
 
         let items = workspace
-            .update(&mut cx, |workspace, cx| workspace.open_paths(abs_paths, cx))
+            .update(&mut cx, |workspace, cx| {
+                workspace.open_paths(abs_paths, true, cx)
+            })
             .await;
 
         if let Some(project) = new_project {

crates/zed/src/zed.rs 🔗

@@ -322,7 +322,7 @@ fn open_config_file(
         workspace
             .update(&mut cx, |workspace, cx| {
                 if workspace.project().read(cx).is_local() {
-                    workspace.open_paths(vec![path.to_path_buf()], cx)
+                    workspace.open_paths(vec![path.to_path_buf()], false, cx)
                 } else {
                     let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
                         let mut workspace = Workspace::new(
@@ -341,7 +341,7 @@ fn open_config_file(
                         workspace
                     });
                     workspace.update(cx, |workspace, cx| {
-                        workspace.open_paths(vec![path.to_path_buf()], cx)
+                        workspace.open_paths(vec![path.to_path_buf()], false, cx)
                     })
                 }
             })
@@ -576,6 +576,7 @@ mod tests {
         fs.insert_file("/dir1/a.txt", "".into()).await;
         fs.insert_file("/dir2/b.txt", "".into()).await;
         fs.insert_file("/dir3/c.txt", "".into()).await;
+        fs.insert_file("/d.txt", "".into()).await;
 
         let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await;
         let (_, workspace) = cx.add_window(|cx| Workspace::new(project, cx));
@@ -583,7 +584,7 @@ mod tests {
         // Open a file within an existing worktree.
         cx.update(|cx| {
             workspace.update(cx, |view, cx| {
-                view.open_paths(vec!["/dir1/a.txt".into()], cx)
+                view.open_paths(vec!["/dir1/a.txt".into()], true, cx)
             })
         })
         .await;
@@ -607,7 +608,7 @@ mod tests {
         // Open a file outside of any existing worktree.
         cx.update(|cx| {
             workspace.update(cx, |view, cx| {
-                view.open_paths(vec!["/dir2/b.txt".into()], cx)
+                view.open_paths(vec!["/dir2/b.txt".into()], true, cx)
             })
         })
         .await;
@@ -643,7 +644,7 @@ mod tests {
         // Ensure opening a directory and one of its children only adds one worktree.
         cx.update(|cx| {
             workspace.update(cx, |view, cx| {
-                view.open_paths(vec!["/dir3".into(), "/dir3/c.txt".into()], cx)
+                view.open_paths(vec!["/dir3".into(), "/dir3/c.txt".into()], true, cx)
             })
         })
         .await;
@@ -675,6 +676,56 @@ mod tests {
                 "c.txt"
             );
         });
+
+        // Ensure opening invisibly a file outside an existing worktree adds a new, invisible worktree.
+        cx.update(|cx| {
+            workspace.update(cx, |view, cx| {
+                view.open_paths(vec!["/d.txt".into()], false, cx)
+            })
+        })
+        .await;
+        cx.read(|cx| {
+            let worktree_roots = workspace
+                .read(cx)
+                .worktrees(cx)
+                .map(|w| w.read(cx).as_local().unwrap().abs_path().as_ref())
+                .collect::<HashSet<_>>();
+            assert_eq!(
+                worktree_roots,
+                vec!["/dir1", "/dir2/b.txt", "/dir3", "/d.txt"]
+                    .into_iter()
+                    .map(Path::new)
+                    .collect(),
+            );
+
+            let visible_worktree_roots = workspace
+                .read(cx)
+                .visible_worktrees(cx)
+                .map(|w| w.read(cx).as_local().unwrap().abs_path().as_ref())
+                .collect::<HashSet<_>>();
+            assert_eq!(
+                visible_worktree_roots,
+                vec!["/dir1", "/dir2/b.txt", "/dir3"]
+                    .into_iter()
+                    .map(Path::new)
+                    .collect(),
+            );
+
+            assert_eq!(
+                workspace
+                    .read(cx)
+                    .active_pane()
+                    .read(cx)
+                    .active_item()
+                    .unwrap()
+                    .to_any()
+                    .downcast::<Editor>()
+                    .unwrap()
+                    .read(cx)
+                    .title(cx),
+                "d.txt"
+            );
+        });
     }
 
     #[gpui::test]
@@ -692,7 +743,7 @@ mod tests {
         // Open a file within an existing worktree.
         cx.update(|cx| {
             workspace.update(cx, |view, cx| {
-                view.open_paths(vec![PathBuf::from("/root/a.txt")], cx)
+                view.open_paths(vec![PathBuf::from("/root/a.txt")], true, cx)
             })
         })
         .await;