diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index e487b64c4e97591c8bb56a17ed01a0d091a2f57c..592e6c9a5318b09cb92e01be484d099dfa526c99 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -388,6 +388,7 @@ struct FakeFsState { event_txs: Vec>>, events_paused: bool, buffered_events: Vec, + metadata_call_count: usize, read_dir_call_count: usize, } @@ -538,6 +539,7 @@ impl FakeFs { buffered_events: Vec::new(), events_paused: false, read_dir_call_count: 0, + metadata_call_count: 0, }), }) } @@ -774,10 +776,16 @@ impl FakeFs { result } + /// How many `read_dir` calls have been issued. pub fn read_dir_call_count(&self) -> usize { self.state.lock().read_dir_call_count } + /// How many `metadata` calls have been issued. + pub fn metadata_call_count(&self) -> usize { + self.state.lock().metadata_call_count + } + async fn simulate_random_delay(&self) { self.executor .upgrade() @@ -1098,7 +1106,8 @@ impl Fs for FakeFs { async fn metadata(&self, path: &Path) -> Result> { self.simulate_random_delay().await; let path = normalize_path(path); - let state = self.state.lock(); + let mut state = self.state.lock(); + state.metadata_call_count += 1; if let Some((mut entry, _)) = state.try_read_path(&path, false) { let is_symlink = entry.lock().is_symlink(); if is_symlink { diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 2084b98381b49dfe411c3f77fe4e35a7645d0959..4eb7aed2e55b29d1827c0861db3cb816b9293a5d 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -3774,25 +3774,22 @@ impl BackgroundScanner { // Scan any directories that were previously ignored and weren't // previously scanned. - if was_ignored - && !entry.is_ignored - && !entry.is_external - && entry.kind == EntryKind::UnloadedDir - { - job.scan_queue - .try_send(ScanJob { - abs_path: abs_path.clone(), - path: entry.path.clone(), - ignore_stack: child_ignore_stack.clone(), - scan_queue: job.scan_queue.clone(), - ancestor_inodes: self - .state - .lock() - .snapshot - .ancestor_inodes_for_path(&entry.path), - is_external: false, - }) - .unwrap(); + if was_ignored && !entry.is_ignored && entry.kind.is_unloaded() { + let state = self.state.lock(); + if state.should_scan_directory(&entry) { + job.scan_queue + .try_send(ScanJob { + abs_path: abs_path.clone(), + path: entry.path.clone(), + ignore_stack: child_ignore_stack.clone(), + scan_queue: job.scan_queue.clone(), + ancestor_inodes: state + .snapshot + .ancestor_inodes_for_path(&entry.path), + is_external: false, + }) + .unwrap(); + } } job.ignore_queue diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index 553c5e2ccafa754623fb0ee85d0c63eccc8ea9e9..f908d702eb22aeb7dfb02eb4300611b7d22fbd73 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -454,6 +454,10 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) { "b1.js": "b1", "b2.js": "b2", }, + "c": { + "c1.js": "c1", + "c2.js": "c2", + } }, }, "two": { @@ -521,6 +525,7 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) { (Path::new("one/node_modules/b"), true), (Path::new("one/node_modules/b/b1.js"), true), (Path::new("one/node_modules/b/b2.js"), true), + (Path::new("one/node_modules/c"), true), (Path::new("two"), false), (Path::new("two/x.js"), false), (Path::new("two/y.js"), false), @@ -564,6 +569,7 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) { (Path::new("one/node_modules/b"), true), (Path::new("one/node_modules/b/b1.js"), true), (Path::new("one/node_modules/b/b2.js"), true), + (Path::new("one/node_modules/c"), true), (Path::new("two"), false), (Path::new("two/x.js"), false), (Path::new("two/y.js"), false), @@ -578,6 +584,17 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) { // Only the newly-expanded directory is scanned. assert_eq!(fs.read_dir_call_count() - prev_read_dir_count, 1); }); + + // No work happens when files and directories change within an unloaded directory. + let prev_fs_call_count = fs.read_dir_call_count() + fs.metadata_call_count(); + fs.create_dir("/root/one/node_modules/c/lib".as_ref()) + .await + .unwrap(); + cx.foreground().run_until_parked(); + assert_eq!( + fs.read_dir_call_count() + fs.metadata_call_count() - prev_fs_call_count, + 0 + ); } #[gpui::test]