@@ -388,6 +388,7 @@ struct FakeFsState {
event_txs: Vec<smol::channel::Sender<Vec<fsevent::Event>>>,
events_paused: bool,
buffered_events: Vec<fsevent::Event>,
+ 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<Option<Metadata>> {
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 {
@@ -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
@@ -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]