From e1a8a31fa40007141def8c862f0ec0e96f8c155a Mon Sep 17 00:00:00 2001 From: Cole Miller Date: Wed, 2 Apr 2025 13:43:48 -0400 Subject: [PATCH] Fix flickering when staging and unstaging files (#27931) This fixes a bug in #27568 that caused flickering in the git panel's checkbox state when staging and unstaging entire files. The problem is that that stage/unstage action first saves the target path (if it's open as a buffer), and we do a targeted git status scan in response to that filesystem event, which makes its way to the git panel and causes it to clear its pending state before the actual stage or unstage has gone through. The fix is to not clear the panel's pending state for git repository events that originated from a targeted scan (i.e. one that was triggered by FS events for repo paths, as opposed to events inside `.git` which cause all statuses to be recomputed). Release Notes: - N/A --- crates/editor/src/git/blame.rs | 2 +- crates/git_ui/src/git_panel.rs | 8 ++++++-- crates/git_ui/src/project_diff.rs | 2 +- crates/project/src/git_store.rs | 8 ++++---- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/editor/src/git/blame.rs b/crates/editor/src/git/blame.rs index 87fa8d13b3c87e13f951e5c84b744a52dfc18084..a6485c4cf673c9875064ff952141b33601b4590c 100644 --- a/crates/editor/src/git/blame.rs +++ b/crates/editor/src/git/blame.rs @@ -212,7 +212,7 @@ impl GitBlame { let git_store = project.read(cx).git_store().clone(); let git_store_subscription = cx.subscribe(&git_store, move |this, _, event, cx| match event { - GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated, _) + GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated { .. }, _) | GitStoreEvent::RepositoryAdded(_) | GitStoreEvent::RepositoryRemoved(_) => { log::debug!("Status of git repositories updated. Regenerating blame data...",); diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 9c2e801ada4b2b82951054bd63d2a211cc3cc50d..2d662a5a2c18de4cc42311171cfcca7b0defb163 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -408,8 +408,12 @@ impl GitPanel { this.active_repository = git_store.read(cx).active_repository(); this.schedule_update(true, window, cx); } - GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated, true) => { - this.schedule_update(true, window, cx); + GitStoreEvent::RepositoryUpdated( + _, + RepositoryEvent::Updated { full_scan }, + true, + ) => { + this.schedule_update(*full_scan, window, cx); } GitStoreEvent::RepositoryUpdated(_, _, _) => {} GitStoreEvent::RepositoryAdded(_) | GitStoreEvent::RepositoryRemoved(_) => { diff --git a/crates/git_ui/src/project_diff.rs b/crates/git_ui/src/project_diff.rs index 697e2e4277ba5e60a0014dae97f4d30de45c2901..fac11a5aa37965d7c17ef1bf75ad47227775ed4a 100644 --- a/crates/git_ui/src/project_diff.rs +++ b/crates/git_ui/src/project_diff.rs @@ -154,7 +154,7 @@ impl ProjectDiff { window, move |this, _git_store, event, _window, _cx| match event { GitStoreEvent::ActiveRepositoryChanged(_) - | GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated, true) => { + | GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated { .. }, true) => { *this.update_needed.borrow_mut() = (); } _ => {} diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index f5ccf93947802b06e6d03618a96c2fd3ba168b3b..a58cc699bf5c0cd96b6ca44656b638078414f236 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -258,7 +258,7 @@ pub enum RepositoryState { #[derive(Clone, Debug)] pub enum RepositoryEvent { - Updated, + Updated { full_scan: bool }, MergeHeadsChanged, } @@ -3521,7 +3521,7 @@ impl Repository { if update.is_last_update { self.snapshot.scan_id = update.scan_id; } - cx.emit(RepositoryEvent::Updated); + cx.emit(RepositoryEvent::Updated { full_scan: true }); Ok(()) } @@ -3866,7 +3866,7 @@ impl Repository { .ok(); } } - cx.emit(RepositoryEvent::Updated); + cx.emit(RepositoryEvent::Updated { full_scan: false }); }) }, ); @@ -4106,7 +4106,7 @@ async fn compute_snapshot( || branch != prev_snapshot.branch || statuses_by_path != prev_snapshot.statuses_by_path { - events.push(RepositoryEvent::Updated); + events.push(RepositoryEvent::Updated { full_scan: true }); } let mut current_merge_conflicts = TreeSet::default();