git: Do not rescan .git on fsmonitor events (#18326)

Fixes #16404 by ignoring events coming from
.git/fsmonitor--daemon/cookies subdirectory.

Closes #16404

Release Notes:

- Improved performance in repositories using Git fsmonitor--daemon
feature.
This commit is contained in:
Piotr Osiewicz 2024-09-25 11:34:27 +02:00 committed by GitHub
parent 7bb510971a
commit 623a6eca75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 2 deletions

View file

@ -18,6 +18,9 @@ pub mod repository;
pub mod status;
pub static DOT_GIT: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new(".git"));
pub static COOKIES: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new("cookies"));
pub static FSMONITOR_DAEMON: LazyLock<&'static OsStr> =
LazyLock::new(|| OsStr::new("fsmonitor--daemon"));
pub static GITIGNORE: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new(".gitignore"));
#[derive(Clone, Copy, Eq, Hash, PartialEq)]

View file

@ -22,7 +22,7 @@ use fuzzy::CharBag;
use git::{
repository::{GitFileStatus, GitRepository, RepoPath},
status::GitStatus,
DOT_GIT, GITIGNORE,
COOKIES, DOT_GIT, FSMONITOR_DAEMON, GITIGNORE,
};
use gpui::{
AppContext, AsyncAppContext, BackgroundExecutor, Context, EventEmitter, Model, ModelContext,
@ -3707,9 +3707,32 @@ impl BackgroundScanner {
let snapshot = &self.state.lock().snapshot;
{
let mut is_git_related = false;
// We don't want to trigger .git rescan for events within .git/fsmonitor--daemon/cookies directory.
#[derive(PartialEq)]
enum FsMonitorParseState {
Cookies,
FsMonitor
}
let mut fsmonitor_parse_state = None;
if let Some(dot_git_dir) = abs_path
.ancestors()
.find(|ancestor| ancestor.file_name() == Some(*DOT_GIT))
.find(|ancestor| {
let file_name = ancestor.file_name();
if file_name == Some(*COOKIES) {
fsmonitor_parse_state = Some(FsMonitorParseState::Cookies);
false
} else if fsmonitor_parse_state == Some(FsMonitorParseState::Cookies) && file_name == Some(*FSMONITOR_DAEMON) {
fsmonitor_parse_state = Some(FsMonitorParseState::FsMonitor);
false
} else if fsmonitor_parse_state != Some(FsMonitorParseState::FsMonitor) && file_name == Some(*DOT_GIT) {
true
} else {
fsmonitor_parse_state.take();
false
}
})
{
let dot_git_path = dot_git_dir
.strip_prefix(&root_canonical_path)