1use std::{path::Path, sync::Arc};
2
3use crate::init_test;
4use fs::FakeFs;
5use project::{Project, ProjectEntryId, project_search::PathInclusionMatcher, search::SearchQuery};
6use serde_json::json;
7use settings::Settings;
8use util::{
9 path,
10 paths::{PathMatcher, PathStyle},
11 rel_path::RelPath,
12};
13use worktree::{Entry, EntryKind, WorktreeSettings};
14
15#[gpui::test]
16async fn test_path_inclusion_matcher(cx: &mut gpui::TestAppContext) {
17 init_test(cx);
18
19 let fs = FakeFs::new(cx.background_executor.clone());
20 fs.insert_tree(
21 "/root",
22 json!({
23 ".gitignore": "src/data/\n",
24 "src": {
25 "data": {
26 "main.csv": "field_1,field_2,field_3",
27 },
28 "lib": {
29 "main.txt": "Are you familiar with fields?",
30 },
31 },
32 }),
33 )
34 .await;
35
36 let project = Project::test(fs.clone(), [path!("/root").as_ref()], cx).await;
37 let worktree = project.update(cx, |project, cx| project.worktrees(cx).next().unwrap());
38 let (worktree_settings, worktree_snapshot) = worktree.update(cx, |worktree, cx| {
39 let settings_location = worktree.settings_location(cx);
40 return (
41 WorktreeSettings::get(Some(settings_location), cx).clone(),
42 worktree.snapshot(),
43 );
44 });
45
46 // Manually create a test entry for the gitignored directory since it won't
47 // be loaded by the worktree
48 let entry = Entry {
49 id: ProjectEntryId::from_proto(1),
50 kind: EntryKind::UnloadedDir,
51 path: Arc::from(RelPath::unix(Path::new("src/data")).unwrap()),
52 inode: 0,
53 mtime: None,
54 canonical_path: None,
55 is_ignored: true,
56 is_hidden: false,
57 is_always_included: false,
58 is_external: false,
59 is_private: false,
60 size: 0,
61 char_bag: Default::default(),
62 is_fifo: false,
63 };
64
65 // 1. Test searching for `field`, including ignored files without any
66 // inclusion and exclusion filters.
67 let include_ignored = true;
68 let files_to_include = PathMatcher::default();
69 let files_to_exclude = PathMatcher::default();
70 let match_full_paths = false;
71 let search_query = SearchQuery::text(
72 "field",
73 false,
74 false,
75 include_ignored,
76 files_to_include,
77 files_to_exclude,
78 match_full_paths,
79 None,
80 )
81 .unwrap();
82
83 let path_matcher = PathInclusionMatcher::new(Arc::new(search_query));
84 assert!(path_matcher.should_scan_gitignored_dir(
85 &entry,
86 &worktree_snapshot,
87 &worktree_settings
88 ));
89
90 // 2. Test searching for `field`, including ignored files but updating
91 // `files_to_include` to only include files under `src/lib`.
92 let include_ignored = true;
93 let files_to_include = PathMatcher::new(vec!["src/lib"], PathStyle::Posix).unwrap();
94 let files_to_exclude = PathMatcher::default();
95 let match_full_paths = false;
96 let search_query = SearchQuery::text(
97 "field",
98 false,
99 false,
100 include_ignored,
101 files_to_include,
102 files_to_exclude,
103 match_full_paths,
104 None,
105 )
106 .unwrap();
107
108 let path_matcher = PathInclusionMatcher::new(Arc::new(search_query));
109 assert!(!path_matcher.should_scan_gitignored_dir(
110 &entry,
111 &worktree_snapshot,
112 &worktree_settings
113 ));
114}