From bba65e120d9c6dcdaecfb24cf2a861ec93e61375 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Apr 2022 11:06:17 +0200 Subject: [PATCH] Add only one worktree when running `zed /dir /dir/file` --- crates/file_finder/src/file_finder.rs | 2 +- crates/journal/src/journal.rs | 2 +- crates/workspace/src/workspace.rs | 75 +++++++++++++++------------ crates/zed/src/zed.rs | 52 +++++++++++++++++-- 4 files changed, 90 insertions(+), 41 deletions(-) diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index b433193456..ae4110e798 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -469,7 +469,7 @@ mod tests { workspace .update(cx, |workspace, cx| { workspace.open_paths( - &[PathBuf::from("/root/dir1"), PathBuf::from("/root/dir2")], + vec![PathBuf::from("/root/dir1"), PathBuf::from("/root/dir2")], cx, ) }) diff --git a/crates/journal/src/journal.rs b/crates/journal/src/journal.rs index 026ea28718..6e579d87a7 100644 --- a/crates/journal/src/journal.rs +++ b/crates/journal/src/journal.rs @@ -49,7 +49,7 @@ pub fn new_journal_entry(app_state: Arc, cx: &mut MutableAppContext) { let opened = workspace .update(&mut cx, |workspace, cx| { - workspace.open_paths(&[entry_path], cx) + workspace.open_paths(vec![entry_path], cx) }) .await; diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 6ca0b3cbcd..1151fd42c7 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -859,44 +859,49 @@ impl Workspace { pub fn open_paths( &mut self, - abs_paths: &[PathBuf], + mut abs_paths: Vec, cx: &mut ViewContext, ) -> Task, Arc>>>> { - let entries = abs_paths - .iter() - .cloned() - .map(|path| self.project_path_for_path(&path, cx)) - .collect::>(); - let fs = self.fs.clone(); - let tasks = abs_paths - .iter() - .cloned() - .zip(entries.into_iter()) - .map(|(abs_path, project_path)| { - cx.spawn(|this, mut cx| { - let fs = fs.clone(); - async move { - let project_path = project_path.await.ok()?; - if fs.is_file(&abs_path).await { - Some( - this.update(&mut cx, |this, cx| this.open_path(project_path, cx)) - .await, - ) - } else { - None - } - } - }) - }) - .collect::>(); - cx.foreground().spawn(async move { - let mut items = Vec::new(); - for task in tasks { - items.push(task.await); + // Sort the paths to ensure we add worktrees for parents before their children. + abs_paths.sort_unstable(); + cx.spawn(|this, mut cx| async move { + 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(), + ); } - items + + let tasks = abs_paths + .iter() + .cloned() + .zip(entries.into_iter()) + .map(|(abs_path, project_path)| { + let this = this.clone(); + cx.spawn(|mut cx| { + let fs = fs.clone(); + async move { + let project_path = project_path?; + if fs.is_file(&abs_path).await { + Some( + this.update(&mut cx, |this, cx| { + this.open_path(project_path, cx) + }) + .await, + ) + } else { + None + } + } + }) + }) + .collect::>(); + + futures::future::join_all(tasks).await }) } @@ -2152,7 +2157,9 @@ pub fn open_paths( .1 }); - let task = workspace.update(cx, |workspace, cx| workspace.open_paths(abs_paths, cx)); + let task = workspace.update(cx, |workspace, cx| { + workspace.open_paths(abs_paths.to_vec(), cx) + }); cx.spawn(|_| async move { let items = task.await; (workspace, items, is_new_workspace) diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 33525400dd..a07dedfa97 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -283,7 +283,7 @@ fn open_config_file( workspace .update(&mut cx, |workspace, cx| { if workspace.project().read(cx).is_local() { - workspace.open_paths(&[path.to_path_buf()], cx) + workspace.open_paths(vec![path.to_path_buf()], cx) } else { let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| { let project = Project::local( @@ -296,7 +296,7 @@ fn open_config_file( (app_state.build_workspace)(project, &app_state, cx) }); workspace.update(cx, |workspace, cx| { - workspace.open_paths(&[path.to_path_buf()], cx) + workspace.open_paths(vec![path.to_path_buf()], cx) }) } }) @@ -536,8 +536,10 @@ mod tests { let fs = app_state.fs.as_fake(); fs.insert_dir("/dir1").await; fs.insert_dir("/dir2").await; + fs.insert_dir("/dir3").await; fs.insert_file("/dir1/a.txt", "".into()).await; fs.insert_file("/dir2/b.txt", "".into()).await; + fs.insert_file("/dir3/c.txt", "".into()).await; let params = cx.update(|cx| WorkspaceParams::local(&app_state, cx)); let (_, workspace) = cx.add_window(|cx| Workspace::new(¶ms, cx)); @@ -553,7 +555,9 @@ mod tests { // Open a file within an existing worktree. cx.update(|cx| { - workspace.update(cx, |view, cx| view.open_paths(&["/dir1/a.txt".into()], cx)) + workspace.update(cx, |view, cx| { + view.open_paths(vec!["/dir1/a.txt".into()], cx) + }) }) .await; cx.read(|cx| { @@ -575,7 +579,9 @@ mod tests { // Open a file outside of any existing worktree. cx.update(|cx| { - workspace.update(cx, |view, cx| view.open_paths(&["/dir2/b.txt".into()], cx)) + workspace.update(cx, |view, cx| { + view.open_paths(vec!["/dir2/b.txt".into()], cx) + }) }) .await; cx.read(|cx| { @@ -606,6 +612,42 @@ mod tests { "b.txt" ); }); + + // 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) + }) + }) + .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::>(); + assert_eq!( + 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::() + .unwrap() + .read(cx) + .title(cx), + "c.txt" + ); + }); } #[gpui::test] @@ -627,7 +669,7 @@ mod tests { // Open a file within an existing worktree. cx.update(|cx| { workspace.update(cx, |view, cx| { - view.open_paths(&[PathBuf::from("/root/a.txt")], cx) + view.open_paths(vec![PathBuf::from("/root/a.txt")], cx) }) }) .await;