From 623a6eca75cb941ea7a368e133097605882efbb9 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:34:27 +0200 Subject: [PATCH] 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. --- crates/git/src/git.rs | 3 +++ crates/worktree/src/worktree.rs | 27 +++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/crates/git/src/git.rs b/crates/git/src/git.rs index 20629899e8c0cfd2f737705ee447b85ec684ba89..fb204fba8266abbf8f2d0b7bb585f1705b0abf2e 100644 --- a/crates/git/src/git.rs +++ b/crates/git/src/git.rs @@ -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)] diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index d8555b71a4f67c6b83065e44e1576a17057336c1..550843e51e448ca5b03a2f6ec080bf1363e64cfc 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -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)