diff --git a/server/src/tests.rs b/server/src/tests.rs index e65e471c8b3c04654c44ffc2b4cfcad38c985581..d3dc59bea6cd66c148292b437db71256009dab08 100644 --- a/server/src/tests.rs +++ b/server/src/tests.rs @@ -39,8 +39,14 @@ async fn test_share_worktree(mut cx_a: TestAppContext, mut cx_b: TestAppContext) "a.txt": "a-contents", "b.txt": "b-contents", })); - let worktree_a = cx_a - .add_model(|cx| Worktree::local(dir.path(), lang_registry.clone(), Arc::new(RealFs), cx)); + let worktree_a = Worktree::open_local( + dir.path(), + lang_registry.clone(), + Arc::new(RealFs), + &mut cx_a.to_async(), + ) + .await + .unwrap(); worktree_a .read_with(&cx_a, |tree, _| tree.as_local().unwrap().scan_complete()) .await; @@ -134,8 +140,14 @@ async fn test_propagate_saves_and_fs_changes_in_shared_worktree( "file1": "", "file2": "" })); - let worktree_a = cx_a - .add_model(|cx| Worktree::local(dir.path(), lang_registry.clone(), Arc::new(RealFs), cx)); + let worktree_a = Worktree::open_local( + dir.path(), + lang_registry.clone(), + Arc::new(RealFs), + &mut cx_a.to_async(), + ) + .await + .unwrap(); worktree_a .read_with(&cx_a, |tree, _| tree.as_local().unwrap().scan_complete()) .await; @@ -249,8 +261,14 @@ async fn test_buffer_conflict_after_save(mut cx_a: TestAppContext, mut cx_b: Tes fs.save(Path::new("/a.txt"), &"a-contents".into()) .await .unwrap(); - let worktree_a = - cx_a.add_model(|cx| Worktree::local(Path::new("/"), lang_registry.clone(), fs.clone(), cx)); + let worktree_a = Worktree::open_local( + "/".as_ref(), + lang_registry.clone(), + Arc::new(RealFs), + &mut cx_a.to_async(), + ) + .await + .unwrap(); worktree_a .read_with(&cx_a, |tree, _| tree.as_local().unwrap().scan_complete()) .await; @@ -320,8 +338,14 @@ async fn test_editing_while_guest_opens_buffer(mut cx_a: TestAppContext, mut cx_ fs.save(Path::new("/a.txt"), &"a-contents".into()) .await .unwrap(); - let worktree_a = - cx_a.add_model(|cx| Worktree::local(Path::new("/"), lang_registry.clone(), fs.clone(), cx)); + let worktree_a = Worktree::open_local( + "/".as_ref(), + lang_registry.clone(), + Arc::new(RealFs), + &mut cx_a.to_async(), + ) + .await + .unwrap(); worktree_a .read_with(&cx_a, |tree, _| tree.as_local().unwrap().scan_complete()) .await; @@ -373,8 +397,14 @@ async fn test_peer_disconnection(mut cx_a: TestAppContext, cx_b: TestAppContext) "a.txt": "a-contents", "b.txt": "b-contents", })); - let worktree_a = cx_a - .add_model(|cx| Worktree::local(dir.path(), lang_registry.clone(), Arc::new(RealFs), cx)); + let worktree_a = Worktree::open_local( + dir.path(), + lang_registry.clone(), + Arc::new(RealFs), + &mut cx_a.to_async(), + ) + .await + .unwrap(); worktree_a .read_with(&cx_a, |tree, _| tree.as_local().unwrap().scan_complete()) .await; diff --git a/zed/src/editor/buffer.rs b/zed/src/editor/buffer.rs index fc3524b5eae141a4b2678056a374bcd381e92ae4..9b4f8980027fa5a538123dd2c6ca3fec0c822603 100644 --- a/zed/src/editor/buffer.rs +++ b/zed/src/editor/buffer.rs @@ -3209,8 +3209,14 @@ mod tests { "file2": "def", "file3": "ghi", })); - let tree = cx - .add_model(|cx| Worktree::local(dir.path(), Default::default(), Arc::new(RealFs), cx)); + let tree = Worktree::open_local( + dir.path(), + Default::default(), + Arc::new(RealFs), + &mut cx.to_async(), + ) + .await + .unwrap(); tree.flush_fs_events(&cx).await; cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; @@ -3322,8 +3328,14 @@ mod tests { async fn test_file_changes_on_disk(mut cx: gpui::TestAppContext) { let initial_contents = "aaa\nbbbbb\nc\n"; let dir = temp_tree(json!({ "the-file": initial_contents })); - let tree = cx - .add_model(|cx| Worktree::local(dir.path(), Default::default(), Arc::new(RealFs), cx)); + let tree = Worktree::open_local( + dir.path(), + Default::default(), + Arc::new(RealFs), + &mut cx.to_async(), + ) + .await + .unwrap(); cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; diff --git a/zed/src/file_finder.rs b/zed/src/file_finder.rs index 46abbdc5c0163029f97b2b74d98662f6d560ca95..33259f5ff71c38e5166b2adf1450580b543d82bc 100644 --- a/zed/src/file_finder.rs +++ b/zed/src/file_finder.rs @@ -476,11 +476,13 @@ mod tests { }); let app_state = cx.read(build_app_state); - let (window_id, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree(tmp_dir.path(), cx); - workspace - }); + let (window_id, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree(tmp_dir.path(), cx) + }) + .await + .unwrap(); cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) .await; cx.dispatch_action( @@ -543,11 +545,13 @@ mod tests { "hiccup": "", })); let app_state = cx.read(build_app_state); - let (_, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree(tmp_dir.path(), cx); - workspace - }); + let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree(tmp_dir.path(), cx) + }) + .await + .unwrap(); cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) .await; let (_, finder) = @@ -601,11 +605,13 @@ mod tests { fs::write(&file_path, "").unwrap(); let app_state = cx.read(build_app_state); - let (_, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree(&file_path, cx); - workspace - }); + let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree(&file_path, cx) + }) + .await + .unwrap(); cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) .await; let (_, finder) = diff --git a/zed/src/workspace.rs b/zed/src/workspace.rs index 3b71e07cc245b655f9f2da432b3f655cd3908d63..577470fa62f51ab066dcc770a9e80f334bfc7f68 100644 --- a/zed/src/workspace.rs +++ b/zed/src/workspace.rs @@ -402,70 +402,89 @@ impl Workspace { cx.spawn(|this, mut cx| { let fs = fs.clone(); async move { + let entry_id = entry_id.await?; if fs.is_file(&abs_path).await { - return this.update(&mut cx, |this, cx| this.open_entry(entry_id, cx)); - } else { - None + if let Some(entry) = + this.update(&mut cx, |this, cx| this.open_entry(entry_id, cx)) + { + entry.await; + } } + Ok(()) } }) }) - .collect::>(); + .collect::>>>(); async move { for task in tasks { - if let Some(task) = task.await { - task.await; + if let Err(error) = task.await { + log::error!("error opening paths {}", error); } } } } fn worktree_for_abs_path( - &mut self, + &self, abs_path: &Path, cx: &mut ViewContext, - ) -> (ModelHandle, PathBuf) { - for tree in self.worktrees.iter() { - if let Some(path) = tree - .read(cx) - .as_local() - .and_then(|tree| abs_path.strip_prefix(&tree.abs_path()).ok()) - { - return (tree.clone(), path.to_path_buf()); + ) -> Task, PathBuf)>> { + let abs_path: Arc = Arc::from(abs_path); + cx.spawn(|this, mut cx| async move { + let mut entry_id = None; + this.read_with(&cx, |this, cx| { + for tree in this.worktrees.iter() { + if let Some(relative_path) = tree + .read(cx) + .as_local() + .and_then(|t| abs_path.strip_prefix(t.abs_path()).ok()) + { + entry_id = Some((tree.clone(), relative_path.into())); + break; + } + } + }); + + if let Some(entry_id) = entry_id { + Ok(entry_id) + } else { + let worktree = this + .update(&mut cx, |this, cx| this.add_worktree(&abs_path, cx)) + .await?; + Ok((worktree, PathBuf::new())) } - } - (self.add_worktree(abs_path, cx), PathBuf::new()) + }) } fn entry_id_for_path( - &mut self, + &self, abs_path: &Path, cx: &mut ViewContext, - ) -> (usize, Arc) { - for tree in self.worktrees.iter() { - if let Some(relative_path) = tree - .read(cx) - .as_local() - .and_then(|t| abs_path.strip_prefix(t.abs_path()).ok()) - { - return (tree.id(), relative_path.into()); - } - } - let worktree = self.add_worktree(&abs_path, cx); - (worktree.id(), Path::new("").into()) + ) -> Task)>> { + let entry = self.worktree_for_abs_path(abs_path, cx); + cx.spawn(|_, _| async move { + let (worktree, path) = entry.await?; + Ok((worktree.id(), path.into())) + }) } pub fn add_worktree( - &mut self, + &self, path: &Path, cx: &mut ViewContext, - ) -> ModelHandle { - let worktree = - cx.add_model(|cx| Worktree::local(path, self.languages.clone(), self.fs.clone(), cx)); - cx.observe_model(&worktree, |_, _, cx| cx.notify()); - self.worktrees.insert(worktree.clone()); - cx.notify(); - worktree + ) -> Task>> { + let languages = self.languages.clone(); + let fs = self.fs.clone(); + let path = Arc::from(path); + cx.spawn(|this, mut cx| async move { + let worktree = Worktree::open_local(path, languages, fs, &mut cx).await?; + this.update(&mut cx, |this, cx| { + cx.observe_model(&worktree, |_, _, cx| cx.notify()); + this.worktrees.insert(worktree.clone()); + cx.notify(); + }); + Ok(worktree) + }) } pub fn toggle_modal(&mut self, cx: &mut ViewContext, add_view: F) @@ -640,12 +659,22 @@ impl Workspace { cx.prompt_for_new_path(&start_abs_path, move |abs_path, cx| { if let Some(abs_path) = abs_path { cx.spawn(|mut cx| async move { - let result = handle - .update(&mut cx, |me, cx| { - let (worktree, path) = me.worktree_for_abs_path(&abs_path, cx); - item.save_as(&worktree, &path, cx.as_mut()) + let result = match handle + .update(&mut cx, |this, cx| { + this.worktree_for_abs_path(&abs_path, cx) }) - .await; + .await + { + Ok((worktree, path)) => { + handle + .update(&mut cx, |_, cx| { + item.save_as(&worktree, &path, cx.as_mut()) + }) + .await + } + Err(error) => Err(error), + }; + if let Err(error) = result { error!("failed to save item: {:?}, ", error); } @@ -974,11 +1003,13 @@ mod tests { let app_state = cx.read(build_app_state); - let (_, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree(dir.path(), cx); - workspace - }); + let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree(dir.path(), cx) + }) + .await + .unwrap(); cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) .await; @@ -1077,11 +1108,13 @@ mod tests { let mut app_state = cx.read(build_app_state); Arc::get_mut(&mut app_state).unwrap().fs = Arc::new(fs); - let (_, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree("/dir1".as_ref(), cx); - workspace - }); + let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree("/dir1".as_ref(), cx) + }) + .await + .unwrap(); cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) .await; @@ -1142,11 +1175,13 @@ mod tests { })); let app_state = cx.read(build_app_state); - let (window_id, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree(dir.path(), cx); - workspace - }); + let (window_id, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree(dir.path(), cx) + }) + .await + .unwrap(); let tree = cx.read(|cx| { let mut trees = workspace.read(cx).worktrees().iter(); trees.next().unwrap().clone() @@ -1185,11 +1220,13 @@ mod tests { async fn test_open_and_save_new_file(mut cx: gpui::TestAppContext) { let dir = TempDir::new("test-new-file").unwrap(); let app_state = cx.read(build_app_state); - let (_, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree(dir.path(), cx); - workspace - }); + let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree(dir.path(), cx) + }) + .await + .unwrap(); let tree = cx.read(|cx| { workspace .read(cx) @@ -1305,11 +1342,13 @@ mod tests { })); let app_state = cx.read(build_app_state); - let (window_id, workspace) = cx.add_window(|cx| { - let mut workspace = Workspace::new(&app_state, cx); - workspace.add_worktree(dir.path(), cx); - workspace - }); + let (window_id, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx)); + workspace + .update(&mut cx, |workspace, cx| { + workspace.add_worktree(dir.path(), cx) + }) + .await + .unwrap(); cx.read(|cx| workspace.read(cx).worktree_scans_complete(cx)) .await; let entries = cx.read(|cx| workspace.file_entries(cx)); diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index 53adb76c7f24c6feb90ab00d2170f27031b6064e..6b38887e82a7a105eddeab73ef82e6fdc3284c96 100644 --- a/zed/src/worktree.rs +++ b/zed/src/worktree.rs @@ -541,23 +541,26 @@ impl Entity for Worktree { } impl Worktree { - pub fn local( + pub async fn open_local( path: impl Into>, languages: Arc, fs: Arc, - cx: &mut ModelContext, - ) -> Self { - let (mut tree, scan_states_tx) = LocalWorktree::new(path, languages, fs.clone(), cx); - let abs_path = tree.snapshot.abs_path.clone(); - let background_snapshot = tree.background_snapshot.clone(); - let thread_pool = cx.thread_pool().clone(); - tree._background_scanner_task = Some(cx.background().spawn(async move { - let events = fs.watch(&abs_path, Duration::from_millis(100)).await; - let scanner = - BackgroundScanner::new(background_snapshot, scan_states_tx, fs, thread_pool); - scanner.run(events).await; - })); - Worktree::Local(tree) + cx: &mut AsyncAppContext, + ) -> Result> { + let (tree, scan_states_tx) = LocalWorktree::new(path, languages, fs.clone(), cx).await?; + tree.update(cx, |tree, cx| { + let tree = tree.as_local_mut().unwrap(); + let abs_path = tree.snapshot.abs_path.clone(); + let background_snapshot = tree.background_snapshot.clone(); + let thread_pool = cx.thread_pool().clone(); + tree._background_scanner_task = Some(cx.background().spawn(async move { + let events = fs.watch(&abs_path, Duration::from_millis(100)).await; + let scanner = + BackgroundScanner::new(background_snapshot, scan_states_tx, fs, thread_pool); + scanner.run(events).await; + })); + }); + Ok(tree) } pub async fn open_remote( @@ -1016,75 +1019,99 @@ pub struct LocalWorktree { } impl LocalWorktree { - fn new( + async fn new( path: impl Into>, languages: Arc, fs: Arc, - cx: &mut ModelContext, - ) -> (Self, Sender) { + cx: &mut AsyncAppContext, + ) -> Result<(ModelHandle, Sender)> { let abs_path = path.into(); + let path: Arc = Arc::from(Path::new("")); + let next_entry_id = AtomicUsize::new(0); + + // After determining whether the root entry is a file or a directory, populate the + // snapshot's "root name", which will be used for the purpose of fuzzy matching. + let mut root_name = abs_path + .file_name() + .map_or(String::new(), |f| f.to_string_lossy().to_string()); + let root_char_bag = root_name.chars().map(|c| c.to_ascii_lowercase()).collect(); + let entry = fs + .entry(root_char_bag, &next_entry_id, path.clone(), &abs_path) + .await? + .ok_or_else(|| anyhow!("root entry does not exist"))?; + let is_dir = entry.is_dir(); + if is_dir { + root_name.push('/'); + } + let (scan_states_tx, scan_states_rx) = smol::channel::unbounded(); let (mut last_scan_state_tx, last_scan_state_rx) = watch::channel_with(ScanState::Scanning); - let id = cx.model_id(); - let snapshot = Snapshot { - id, - scan_id: 0, - abs_path, - root_name: Default::default(), - root_char_bag: Default::default(), - ignores: Default::default(), - entries_by_path: Default::default(), - entries_by_id: Default::default(), - removed_entry_ids: Default::default(), - next_entry_id: Default::default(), - }; - - let tree = Self { - snapshot: snapshot.clone(), - background_snapshot: Arc::new(Mutex::new(snapshot)), - snapshots_to_send_tx: None, - last_scan_state_rx, - _background_scanner_task: None, - poll_scheduled: false, - open_buffers: Default::default(), - shared_buffers: Default::default(), - peers: Default::default(), - rpc: None, - languages, - fs, - }; + let tree = cx.add_model(move |cx: &mut ModelContext| { + let mut snapshot = Snapshot { + id: cx.model_id(), + scan_id: 0, + abs_path, + root_name, + root_char_bag, + ignores: Default::default(), + entries_by_path: Default::default(), + entries_by_id: Default::default(), + removed_entry_ids: Default::default(), + next_entry_id: Arc::new(next_entry_id), + }; + snapshot.insert_entry(entry); + + let tree = Self { + snapshot: snapshot.clone(), + background_snapshot: Arc::new(Mutex::new(snapshot)), + snapshots_to_send_tx: None, + last_scan_state_rx, + _background_scanner_task: None, + poll_scheduled: false, + open_buffers: Default::default(), + shared_buffers: Default::default(), + peers: Default::default(), + rpc: None, + languages, + fs, + }; - cx.spawn_weak(|this, mut cx| async move { - while let Ok(scan_state) = scan_states_rx.recv().await { - if let Some(handle) = cx.read(|cx| this.upgrade(&cx)) { - let to_send = handle.update(&mut cx, |this, cx| { - last_scan_state_tx.blocking_send(scan_state).ok(); - this.poll_snapshot(cx); - let tree = this.as_local_mut().unwrap(); - if !tree.is_scanning() { - if let Some(snapshots_to_send_tx) = tree.snapshots_to_send_tx.clone() { - Some((tree.snapshot(), snapshots_to_send_tx)) + cx.spawn_weak(|this, mut cx| async move { + while let Ok(scan_state) = scan_states_rx.recv().await { + if let Some(handle) = cx.read(|cx| this.upgrade(&cx)) { + let to_send = handle.update(&mut cx, |this, cx| { + last_scan_state_tx.blocking_send(scan_state).ok(); + this.poll_snapshot(cx); + let tree = this.as_local_mut().unwrap(); + if !tree.is_scanning() { + if let Some(snapshots_to_send_tx) = + tree.snapshots_to_send_tx.clone() + { + Some((tree.snapshot(), snapshots_to_send_tx)) + } else { + None + } } else { None } - } else { - None - } - }); + }); - if let Some((snapshot, snapshots_to_send_tx)) = to_send { - if let Err(err) = snapshots_to_send_tx.send(snapshot).await { - log::error!("error submitting snapshot to send {}", err); + if let Some((snapshot, snapshots_to_send_tx)) = to_send { + if let Err(err) = snapshots_to_send_tx.send(snapshot).await { + log::error!("error submitting snapshot to send {}", err); + } } + } else { + break; } - } else { - break; } - } - }) - .detach(); + }) + .detach(); + + Worktree::Local(tree) + }); - (tree, scan_states_tx) + Ok((tree, scan_states_tx)) } pub fn open_buffer( @@ -1890,9 +1917,8 @@ impl File { /// Returns the last component of this handle's absolute path. If this handle refers to the root /// of its worktree, then this method will return the name of the worktree itself. pub fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option { - self.path - .file_name() - .or_else(|| Some(OsStr::new(self.worktree.read(cx).root_name()))) + dbg!(self.path.file_name()) + .or_else(|| Some(OsStr::new(dbg!(self.worktree.read(cx).root_name())))) .map(Into::into) } @@ -2242,40 +2268,19 @@ impl BackgroundScanner { } async fn scan_dirs(&mut self) -> Result<()> { + let root_char_bag; let next_entry_id; + let is_dir; { - let mut snapshot = self.snapshot.lock(); - snapshot.scan_id += 1; + let snapshot = self.snapshot.lock(); + root_char_bag = snapshot.root_char_bag; next_entry_id = snapshot.next_entry_id.clone(); + is_dir = snapshot.root_entry().is_dir(); } - let path: Arc = Arc::from(Path::new("")); - let abs_path = self.abs_path(); - - // After determining whether the root entry is a file or a directory, populate the - // snapshot's "root name", which will be used for the purpose of fuzzy matching. - let mut root_name = abs_path - .file_name() - .map_or(String::new(), |f| f.to_string_lossy().to_string()); - let root_char_bag = root_name.chars().map(|c| c.to_ascii_lowercase()).collect(); - let entry = self - .fs - .entry(root_char_bag, &next_entry_id, path.clone(), &abs_path) - .await? - .ok_or_else(|| anyhow!("root entry does not exist"))?; - let is_dir = entry.is_dir(); - if is_dir { - root_name.push('/'); - } - - { - let mut snapshot = self.snapshot.lock(); - snapshot.root_name = root_name; - snapshot.root_char_bag = root_char_bag; - } - - self.snapshot.lock().insert_entry(entry); if is_dir { + let path: Arc = Arc::from(Path::new("")); + let abs_path = self.abs_path(); let (tx, rx) = channel::unbounded(); tx.send(ScanJob { abs_path: abs_path.to_path_buf(), @@ -2983,7 +2988,7 @@ mod tests { use std::{env, fmt::Write, os::unix, time::SystemTime}; #[gpui::test] - async fn test_populate_and_search(mut cx: gpui::TestAppContext) { + async fn test_populate_and_search(cx: gpui::TestAppContext) { let dir = temp_tree(json!({ "root": { "apple": "", @@ -3007,9 +3012,14 @@ mod tests { ) .unwrap(); - let tree = cx.add_model(|cx| { - Worktree::local(root_link_path, Default::default(), Arc::new(RealFs), cx) - }); + let tree = Worktree::open_local( + root_link_path, + Default::default(), + Arc::new(RealFs), + &mut cx.to_async(), + ) + .await + .unwrap(); cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; @@ -3055,14 +3065,14 @@ mod tests { let dir = temp_tree(json!({ "file1": "the old contents", })); - let tree = cx.add_model(|cx| { - Worktree::local( - dir.path(), - app_state.languages.clone(), - Arc::new(RealFs), - cx, - ) - }); + let tree = Worktree::open_local( + dir.path(), + app_state.languages.clone(), + Arc::new(RealFs), + &mut cx.to_async(), + ) + .await + .unwrap(); let buffer = tree .update(&mut cx, |tree, cx| tree.open_buffer("file1", cx)) .await @@ -3085,14 +3095,14 @@ mod tests { })); let file_path = dir.path().join("file1"); - let tree = cx.add_model(|cx| { - Worktree::local( - file_path.clone(), - app_state.languages.clone(), - Arc::new(RealFs), - cx, - ) - }); + let tree = Worktree::open_local( + file_path.clone(), + app_state.languages.clone(), + Arc::new(RealFs), + &mut cx.to_async(), + ) + .await + .unwrap(); cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; cx.read(|cx| assert_eq!(tree.read(cx).file_count(), 1)); @@ -3127,8 +3137,14 @@ mod tests { } })); - let tree = cx - .add_model(|cx| Worktree::local(dir.path(), Default::default(), Arc::new(RealFs), cx)); + let tree = Worktree::open_local( + dir.path(), + Default::default(), + Arc::new(RealFs), + &mut cx.to_async(), + ) + .await + .unwrap(); let buffer_for_path = |path: &'static str, cx: &mut gpui::TestAppContext| { let buffer = tree.update(cx, |tree, cx| tree.open_buffer(path, cx)); @@ -3263,7 +3279,7 @@ mod tests { } #[gpui::test] - async fn test_rescan_with_gitignore(mut cx: gpui::TestAppContext) { + async fn test_rescan_with_gitignore(cx: gpui::TestAppContext) { let dir = temp_tree(json!({ ".git": {}, ".gitignore": "ignored-dir\n", @@ -3275,8 +3291,14 @@ mod tests { } })); - let tree = cx - .add_model(|cx| Worktree::local(dir.path(), Default::default(), Arc::new(RealFs), cx)); + let tree = Worktree::open_local( + dir.path(), + Default::default(), + Arc::new(RealFs), + &mut cx.to_async(), + ) + .await + .unwrap(); cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) .await; tree.flush_fs_events(&cx).await;