Fix panic when fuzzy-matching on a `Worktree` that contains no files
Antonio Scandurra
created 4 years ago
As part of our work on the deterministic executor, in c4e37dc we fixed a
bug that occurred when there were more CPUs than paths to fuzzy-match
on.
However, that introduced another bug that caused Zed to panic when
trying to calculate how many paths should be fuzzy-matched by each
available worker thread for worktrees that didn't contain any file.
This commit bails out early in `fuzzy::match_paths` if the vector of
paths to search is empty.
Change summary
zed/src/worktree.rs | 49 +++++++++++++++++++++++++++++++++++++++++
zed/src/worktree/fuzzy.rs | 15 +++++++-----
2 files changed, 58 insertions(+), 6 deletions(-)
Detailed changes
@@ -2641,6 +2641,55 @@ mod tests {
);
}
+ #[gpui::test]
+ async fn test_search_worktree_without_files(cx: gpui::TestAppContext) {
+ let dir = temp_tree(json!({
+ "root": {
+ "dir1": {},
+ "dir2": {
+ "dir3": {}
+ }
+ }
+ }));
+ 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;
+ let snapshot = cx.read(|cx| {
+ let tree = tree.read(cx);
+ assert_eq!(tree.file_count(), 0);
+ tree.snapshot()
+ });
+ let results = cx
+ .read(|cx| {
+ match_paths(
+ Some(&snapshot).into_iter(),
+ "dir",
+ false,
+ false,
+ false,
+ 10,
+ Default::default(),
+ cx.background().clone(),
+ )
+ })
+ .await;
+ assert_eq!(
+ results
+ .into_iter()
+ .map(|result| result.path)
+ .collect::<Vec<Arc<Path>>>(),
+ vec![]
+ );
+ }
+
#[gpui::test]
async fn test_save_file(mut cx: gpui::TestAppContext) {
let app_state = cx.read(build_app_state);
@@ -64,6 +64,15 @@ pub async fn match_paths<'a, T>(
where
T: Clone + Send + Iterator<Item = &'a Snapshot> + 'a,
{
+ let path_count: usize = if include_ignored {
+ snapshots.clone().map(Snapshot::file_count).sum()
+ } else {
+ snapshots.clone().map(Snapshot::visible_file_count).sum()
+ };
+ if path_count == 0 {
+ return Vec::new();
+ }
+
let lowercase_query = query.to_lowercase().chars().collect::<Vec<_>>();
let query = query.chars().collect::<Vec<_>>();
@@ -71,12 +80,6 @@ where
let query = &query;
let query_chars = CharBag::from(&lowercase_query[..]);
- let path_count: usize = if include_ignored {
- snapshots.clone().map(Snapshot::file_count).sum()
- } else {
- snapshots.clone().map(Snapshot::visible_file_count).sum()
- };
-
let num_cpus = background.num_cpus().min(path_count);
let segment_size = (path_count + num_cpus - 1) / num_cpus;
let mut segment_results = (0..num_cpus)