From 1612c90052fd570fbee7856d5d53c45416d3dcf1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 14 Nov 2023 00:19:51 +0200 Subject: [PATCH] More lenient file path matchers --- crates/project/src/project_settings.rs | 1 - crates/project/src/worktree.rs | 2 +- crates/util/src/paths.rs | 24 +++++++++++++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/crates/project/src/project_settings.rs b/crates/project/src/project_settings.rs index 8aebb380b635c732f424075bb6e44df0fb6b3caf..17233219d74061b7d1382cff4dd8b18408f7961d 100644 --- a/crates/project/src/project_settings.rs +++ b/crates/project/src/project_settings.rs @@ -12,7 +12,6 @@ pub struct ProjectSettings { pub git: GitSettings, // TODO kb better names and docs and tests // TODO kb how to react on their changes? - // TODO kb /something/node_modules/ does not match `"**/node_modules/**"` glob!!! #[serde(default)] pub scan_exclude_files: Vec, } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index dbc18e086d8cb9bf68fb2c24fe24caa8e5b18ac8..3cc1ff6fef635f9b65ad5f148bef8a6787367be2 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -3598,7 +3598,7 @@ impl BackgroundScanner { for entry in &mut new_entries { state.reuse_entry_id(entry); if entry.is_dir() { - if state.should_scan_directory(&entry, &job.path.join(&entry.path)) { + if state.should_scan_directory(&entry, &root_abs_path.join(&entry.path)) { job_ix += 1; } else { log::debug!("defer scanning directory {:?}", entry.path); diff --git a/crates/util/src/paths.rs b/crates/util/src/paths.rs index d54e0b1cd63fc302101c1020d7fb0ff60ee1d5bf..5999bd1d3923a820c6412aa5d1b4c6f2e915e8d3 100644 --- a/crates/util/src/paths.rs +++ b/crates/util/src/paths.rs @@ -211,7 +211,19 @@ impl PathMatcher { } pub fn is_match>(&self, other: P) -> bool { - other.as_ref().starts_with(&self.maybe_path) || self.glob.is_match(other) + other.as_ref().starts_with(&self.maybe_path) + || self.glob.is_match(&other) + || self.check_with_end_separator(other.as_ref()) + } + + fn check_with_end_separator(&self, path: &Path) -> bool { + let path_str = path.to_string_lossy(); + let separator = std::path::MAIN_SEPARATOR_STR; + if path_str.ends_with(separator) { + self.glob.is_match(path) + } else { + self.glob.is_match(path_str.to_string() + separator) + } } } @@ -388,4 +400,14 @@ mod tests { let path = Path::new("/a/b/c/.eslintrc.js"); assert_eq!(path.extension_or_hidden_file_name(), Some("js")); } + + #[test] + fn edge_of_glob() { + let path = Path::new("/work/node_modules"); + let path_matcher = PathMatcher::new("**/node_modules/**").unwrap(); + assert!( + path_matcher.is_match(&path), + "Path matcher {path_matcher} should match {path:?}" + ); + } }