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 87fa8d13b3..a6485c4cf6 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 9c2e801ada..2d662a5a2c 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 697e2e4277..fac11a5aa3 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 f5ccf93947..a58cc699bf 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();