@@ -52,7 +52,7 @@ use std::{
fmt,
future::Future,
mem::{self},
- ops::{Deref, DerefMut},
+ ops::{Deref, DerefMut, Range},
path::{Path, PathBuf},
pin::Pin,
sync::{
@@ -3877,29 +3877,35 @@ impl BackgroundScanner {
abs_paths.dedup_by(|a, b| a.starts_with(b));
{
let snapshot = &self.state.lock().await.snapshot;
- abs_paths.retain(|abs_path| {
- let abs_path = &SanitizedPath::new(abs_path);
+ let mut ranges_to_drop = SmallVec::<[Range<usize>; 4]>::new();
- {
- let mut is_git_related = false;
+ fn skip_ix(ranges: &mut SmallVec<[Range<usize>; 4]>, ix: usize) {
+ if let Some(last_range) = ranges.last_mut()
+ && last_range.end == ix
+ {
+ last_range.end += 1;
+ } else {
+ ranges.push(ix..ix + 1);
+ }
+ }
- let dot_git_paths = self.executor.block(maybe!(async {
- let mut path = None;
- for ancestor in abs_path.as_path().ancestors() {
+ for (ix, abs_path) in abs_paths.iter().enumerate() {
+ let abs_path = &SanitizedPath::new(&abs_path);
+ let mut is_git_related = false;
+ let mut dot_git_paths = None;
+
+ for ancestor in abs_path.as_path().ancestors() {
if is_git_dir(ancestor, self.fs.as_ref()).await {
let path_in_git_dir = abs_path
.as_path()
.strip_prefix(ancestor)
.expect("stripping off the ancestor");
- path = Some((ancestor.to_owned(), path_in_git_dir.to_owned()));
- break;
- }
+ dot_git_paths = Some((ancestor.to_owned(), path_in_git_dir.to_owned()));
+ break;
}
- path
-
- }));
+ }
if let Some((dot_git_abs_path, path_in_git_dir)) = dot_git_paths {
if skipped_files_in_dot_git
@@ -3909,8 +3915,11 @@ impl BackgroundScanner {
path_in_git_dir.starts_with(skipped_git_subdir)
})
{
- log::debug!("ignoring event {abs_path:?} as it's in the .git directory among skipped files or directories");
- return false;
+ log::debug!(
+ "ignoring event {abs_path:?} as it's in the .git directory among skipped files or directories"
+ );
+ skip_ix(&mut ranges_to_drop, ix);
+ continue;
}
is_git_related = true;
@@ -3919,8 +3928,7 @@ impl BackgroundScanner {
}
}
- let relative_path = if let Ok(path) =
- abs_path.strip_prefix(&root_canonical_path)
+ let relative_path = if let Ok(path) = abs_path.strip_prefix(&root_canonical_path)
&& let Ok(path) = RelPath::new(path, PathStyle::local())
{
path
@@ -3931,10 +3939,11 @@ impl BackgroundScanner {
);
} else {
log::error!(
- "ignoring event {abs_path:?} outside of root path {root_canonical_path:?}",
+ "ignoring event {abs_path:?} outside of root path {root_canonical_path:?}",
);
}
- return false;
+ skip_ix(&mut ranges_to_drop, ix);
+ continue;
};
if abs_path.file_name() == Some(OsStr::new(GITIGNORE)) {
@@ -3958,21 +3967,26 @@ impl BackgroundScanner {
});
if !parent_dir_is_loaded {
log::debug!("ignoring event {relative_path:?} within unloaded directory");
- return false;
+ skip_ix(&mut ranges_to_drop, ix);
+ continue;
}
if self.settings.is_path_excluded(&relative_path) {
if !is_git_related {
log::debug!("ignoring FS event for excluded path {relative_path:?}");
}
- return false;
+ skip_ix(&mut ranges_to_drop, ix);
+ continue;
}
relative_paths.push(relative_path.into_arc());
- true
}
- });
+
+ for range_to_drop in ranges_to_drop.into_iter().rev() {
+ abs_paths.drain(range_to_drop);
+ }
}
+
if relative_paths.is_empty() && dot_git_abs_paths.is_empty() {
return;
}