Defer ignored dirs scanning

Kirill Bulatov created

Change summary

crates/project/src/ignore.rs         |  4 ++++
crates/project/src/worktree.rs       | 12 ++++++++----
crates/project/src/worktree_tests.rs |  8 ++++++--
3 files changed, 18 insertions(+), 6 deletions(-)

Detailed changes

crates/project/src/ignore.rs 🔗

@@ -20,6 +20,10 @@ impl IgnoreStack {
         Arc::new(Self::All)
     }
 
+    pub fn is_all(&self) -> bool {
+        matches!(self, Self::All)
+    }
+
     pub fn append(self: Arc<Self>, abs_base_path: Arc<Path>, ignore: Arc<Gitignore>) -> Arc<Self> {
         match self.as_ref() {
             IgnoreStack::All => self,

crates/project/src/worktree.rs 🔗

@@ -2253,9 +2253,7 @@ impl BackgroundScannerState {
         let ignore_stack = self.snapshot.ignore_stack_for_abs_path(&abs_path, true);
         let mut ancestor_inodes = self.snapshot.ancestor_inodes_for_path(&path);
         let mut containing_repository = None;
-        if !matches!(ignore_stack.as_ref(), &IgnoreStack::All)
-            && !self.snapshot.is_abs_path_excluded(&abs_path)
-        {
+        if !ignore_stack.is_all() && !self.snapshot.is_abs_path_excluded(&abs_path) {
             if let Some((workdir_path, repo)) = self.snapshot.local_repo_for_path(&path) {
                 if let Ok(repo_path) = path.strip_prefix(&workdir_path.0) {
                     containing_repository = Some((
@@ -3327,6 +3325,10 @@ impl BackgroundScanner {
                     log::debug!("ignoring event {relative_path:?} within unloaded directory");
                     return false;
                 }
+                if snapshot.is_abs_path_excluded(abs_path) {
+                    log::debug!("ignoring event {relative_path:?} within excluded directory");
+                    return false;
+                }
 
                 relative_paths.push(relative_path);
                 true
@@ -3678,7 +3680,9 @@ impl BackgroundScanner {
         for entry in &mut new_entries {
             state.reuse_entry_id(entry);
             if entry.is_dir() {
-                if state.should_scan_directory(&entry, &root_abs_path.join(&entry.path)) {
+                if !ignore_stack.is_all()
+                    && state.should_scan_directory(&entry, &root_abs_path.join(&entry.path))
+                {
                     job_ix += 1;
                 } else {
                     log::debug!("defer scanning directory {:?}", entry.path);

crates/project/src/worktree_tests.rs 🔗

@@ -2268,14 +2268,18 @@ fn check_worktree_entries(
         );
     }
     for path in expected_ignored_paths {
-        let entry = tree.entry_for_path(path).unwrap();
+        let entry = tree
+            .entry_for_path(path)
+            .unwrap_or_else(|| panic!("Missing entry for expected ignored path '{path}'"));
         assert!(
             entry.is_ignored,
             "expected path '{path}' to be ignored, but got entry: {entry:?}",
         );
     }
     for path in expected_tracked_paths {
-        let entry = tree.entry_for_path(path).unwrap();
+        let entry = tree
+            .entry_for_path(path)
+            .unwrap_or_else(|| panic!("Missing entry for expected tracked path '{path}'"));
         assert!(
             !entry.is_ignored,
             "expected path '{path}' to be tracked, but got entry: {entry:?}",