From d6c0d3c8bd8b4677abeaeb24f573c44581e8a415 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 19 Feb 2026 12:25:36 +0100 Subject: [PATCH] project: Block less in `Respository::paths_changed` (#49584) Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/project/src/git_store.rs | 23 ++++++++++++++--------- crates/project/src/project_search.rs | 19 ++++++++++++++----- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index f5b91c85d93ca01917ce3679cfbf40384c98206b..285546a9aeb73ad647fbdcf5cf8e38e6d583a8ac 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -303,7 +303,7 @@ pub struct Repository { git_store: WeakEntity, // For a local repository, holds paths that have had worktree events since the last status scan completed, // and that should be examined during the next status scan. - paths_needing_status_update: BTreeSet, + paths_needing_status_update: Vec>, job_sender: mpsc::UnboundedSender, active_jobs: HashMap, pending_ops: SumTree, @@ -6197,14 +6197,16 @@ impl Repository { updates_tx: Option>, cx: &mut Context, ) { - self.paths_needing_status_update.extend(paths); + if !paths.is_empty() { + self.paths_needing_status_update.push(paths); + } let this = cx.weak_entity(); let _ = self.send_keyed_job( Some(GitJobKey::RefreshStatuses), None, |state, mut cx| async move { - let (prev_snapshot, mut changed_paths) = this.update(&mut cx, |this, _| { + let (prev_snapshot, changed_paths) = this.update(&mut cx, |this, _| { ( this.snapshot.clone(), mem::take(&mut this.paths_needing_status_update), @@ -6214,15 +6216,18 @@ impl Repository { bail!("not a local repository") }; - let paths = changed_paths.iter().cloned().collect::>(); - if paths.is_empty() { + if changed_paths.is_empty() { return Ok(()); } - let statuses = backend.status(&paths).await?; - let stash_entries = backend.stash_entries().await?; + let stash_entries = backend.stash_entries().await?; let changed_path_statuses = cx .background_spawn(async move { + let mut changed_paths = + changed_paths.into_iter().flatten().collect::>(); + let statuses = backend + .status(&changed_paths.iter().cloned().collect::>()) + .await?; let mut changed_path_statuses = Vec::new(); let prev_statuses = prev_snapshot.statuses_by_path.clone(); let mut cursor = prev_statuses.cursor::(()); @@ -6247,9 +6252,9 @@ impl Repository { .push(Edit::Remove(PathKey(path.as_ref().clone()))); } } - changed_path_statuses + anyhow::Ok(changed_path_statuses) }) - .await; + .await?; this.update(&mut cx, |this, cx| { if this.snapshot.stash_entries != stash_entries { diff --git a/crates/project/src/project_search.rs b/crates/project/src/project_search.rs index f7b3e6bb9444b724201cdc765f1fa1cdc2f8b196..dff3312a3b34dc146153b60d1d5b034fbc720d65 100644 --- a/crates/project/src/project_search.rs +++ b/crates/project/src/project_search.rs @@ -728,9 +728,15 @@ impl RequestHandler<'_> { } async fn handle_find_first_match(&self, mut entry: MatchingEntry) { - _=maybe!(async move { + async move { let abs_path = entry.worktree_root.join(entry.path.path.as_std_path()); - let Some(file) = self.fs.context("Trying to query filesystem in remote project search")?.open_sync(&abs_path).await.log_err() else { + let Some(file) = self + .fs + .context("Trying to query filesystem in remote project search")? + .open_sync(&abs_path) + .await + .log_err() + else { return anyhow::Ok(()); }; @@ -738,12 +744,13 @@ impl RequestHandler<'_> { let file_start = file.fill_buf()?; if let Err(Some(starting_position)) = - std::str::from_utf8(file_start).map_err(|e| e.error_len()) + std::str::from_utf8(file_start).map_err(|e| e.error_len()) { // Before attempting to match the file content, throw away files that have invalid UTF-8 sequences early on; // That way we can still match files in a streaming fashion without having look at "obviously binary" files. log::debug!( - "Invalid UTF-8 sequence in file {abs_path:?} at byte position {starting_position}" + "Invalid UTF-8 sequence in file {abs_path:?} \ + at byte position {starting_position}" ); return Ok(()); } @@ -753,7 +760,9 @@ impl RequestHandler<'_> { entry.should_scan_tx.send(entry.path).await?; } Ok(()) - }).await; + } + .await + .ok(); } async fn handle_scan_path(&self, req: InputPath) {