diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-07-18 15:40:43 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-18 15:40:43 +0100 |
commit | 130e7632acef435caa9bf56e7333e4c28c7dffc7 (patch) | |
tree | ca33f4a791eb41439cee21d6b715b8f89fb80b1e /crates/vfs-notify/src/lib.rs | |
parent | fd6717799c03c9171bb7ec0f50bce98d1dfb44bd (diff) | |
parent | 46ac9ff5e3cf070584d8167150655d091d47e3c2 (diff) |
Merge #5433
5433: Simplify exclusion logic r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/vfs-notify/src/lib.rs')
-rw-r--r-- | crates/vfs-notify/src/lib.rs | 104 |
1 files changed, 47 insertions, 57 deletions
diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs index 6aaa53f63..e1e36612a 100644 --- a/crates/vfs-notify/src/lib.rs +++ b/crates/vfs-notify/src/lib.rs | |||
@@ -6,9 +6,7 @@ | |||
6 | //! | 6 | //! |
7 | //! Hopefully, one day a reliable file watching/walking crate appears on | 7 | //! Hopefully, one day a reliable file watching/walking crate appears on |
8 | //! crates.io, and we can reduce this to trivial glue code. | 8 | //! crates.io, and we can reduce this to trivial glue code. |
9 | mod include; | 9 | use std::convert::TryFrom; |
10 | |||
11 | use std::convert::{TryFrom, TryInto}; | ||
12 | 10 | ||
13 | use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; | 11 | use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; |
14 | use notify::{RecommendedWatcher, RecursiveMode, Watcher}; | 12 | use notify::{RecommendedWatcher, RecursiveMode, Watcher}; |
@@ -16,8 +14,6 @@ use paths::{AbsPath, AbsPathBuf}; | |||
16 | use vfs::loader; | 14 | use vfs::loader; |
17 | use walkdir::WalkDir; | 15 | use walkdir::WalkDir; |
18 | 16 | ||
19 | use crate::include::Include; | ||
20 | |||
21 | #[derive(Debug)] | 17 | #[derive(Debug)] |
22 | pub struct NotifyHandle { | 18 | pub struct NotifyHandle { |
23 | // Relative order of fields below is significant. | 19 | // Relative order of fields below is significant. |
@@ -53,7 +49,7 @@ type NotifyEvent = notify::Result<notify::Event>; | |||
53 | 49 | ||
54 | struct NotifyActor { | 50 | struct NotifyActor { |
55 | sender: loader::Sender, | 51 | sender: loader::Sender, |
56 | config: Vec<(AbsPathBuf, Include, bool)>, | 52 | watched_entries: Vec<loader::Entry>, |
57 | // Drop order is significant. | 53 | // Drop order is significant. |
58 | watcher: Option<(RecommendedWatcher, Receiver<NotifyEvent>)>, | 54 | watcher: Option<(RecommendedWatcher, Receiver<NotifyEvent>)>, |
59 | } | 55 | } |
@@ -66,7 +62,7 @@ enum Event { | |||
66 | 62 | ||
67 | impl NotifyActor { | 63 | impl NotifyActor { |
68 | fn new(sender: loader::Sender) -> NotifyActor { | 64 | fn new(sender: loader::Sender) -> NotifyActor { |
69 | NotifyActor { sender, config: Vec::new(), watcher: None } | 65 | NotifyActor { sender, watched_entries: Vec::new(), watcher: None } |
70 | } | 66 | } |
71 | fn next_event(&self, receiver: &Receiver<Message>) -> Option<Event> { | 67 | fn next_event(&self, receiver: &Receiver<Message>) -> Option<Event> { |
72 | let watcher_receiver = self.watcher.as_ref().map(|(_, receiver)| receiver); | 68 | let watcher_receiver = self.watcher.as_ref().map(|(_, receiver)| receiver); |
@@ -93,15 +89,17 @@ impl NotifyActor { | |||
93 | let n_total = config.load.len(); | 89 | let n_total = config.load.len(); |
94 | self.send(loader::Message::Progress { n_total, n_done: 0 }); | 90 | self.send(loader::Message::Progress { n_total, n_done: 0 }); |
95 | 91 | ||
96 | self.config.clear(); | 92 | self.watched_entries.clear(); |
97 | 93 | ||
98 | for (i, entry) in config.load.into_iter().enumerate() { | 94 | for (i, entry) in config.load.into_iter().enumerate() { |
99 | let watch = config.watch.contains(&i); | 95 | let watch = config.watch.contains(&i); |
96 | if watch { | ||
97 | self.watched_entries.push(entry.clone()) | ||
98 | } | ||
100 | let files = self.load_entry(entry, watch); | 99 | let files = self.load_entry(entry, watch); |
101 | self.send(loader::Message::Loaded { files }); | 100 | self.send(loader::Message::Loaded { files }); |
102 | self.send(loader::Message::Progress { n_total, n_done: i + 1 }); | 101 | self.send(loader::Message::Progress { n_total, n_done: i + 1 }); |
103 | } | 102 | } |
104 | self.config.sort_by(|x, y| x.0.cmp(&y.0)); | ||
105 | } | 103 | } |
106 | Message::Invalidate(path) => { | 104 | Message::Invalidate(path) => { |
107 | let contents = read(path.as_path()); | 105 | let contents = read(path.as_path()); |
@@ -116,34 +114,27 @@ impl NotifyActor { | |||
116 | .into_iter() | 114 | .into_iter() |
117 | .map(|path| AbsPathBuf::try_from(path).unwrap()) | 115 | .map(|path| AbsPathBuf::try_from(path).unwrap()) |
118 | .filter_map(|path| { | 116 | .filter_map(|path| { |
119 | let is_dir = path.is_dir(); | 117 | if path.is_dir() |
120 | let is_file = path.is_file(); | 118 | && self |
121 | 119 | .watched_entries | |
122 | let config_idx = | 120 | .iter() |
123 | match self.config.binary_search_by(|it| it.0.cmp(&path)) { | 121 | .any(|entry| entry.contains_dir(&path)) |
124 | Ok(it) => it, | 122 | { |
125 | Err(it) => it.saturating_sub(1), | 123 | self.watch(path); |
126 | }; | 124 | return None; |
127 | let include = self.config.get(config_idx).and_then(|it| { | ||
128 | let rel_path = path.strip_prefix(&it.0)?; | ||
129 | Some((rel_path, &it.1)) | ||
130 | }); | ||
131 | |||
132 | if let Some((rel_path, include)) = include { | ||
133 | if is_dir && include.exclude_dir(&rel_path) | ||
134 | || is_file && !include.include_file(&rel_path) | ||
135 | { | ||
136 | return None; | ||
137 | } | ||
138 | } | 125 | } |
139 | 126 | ||
140 | if is_dir { | 127 | if !path.is_file() { |
141 | self.watch(path); | ||
142 | return None; | 128 | return None; |
143 | } | 129 | } |
144 | if !is_file { | 130 | if !self |
131 | .watched_entries | ||
132 | .iter() | ||
133 | .any(|entry| entry.contains_file(&path)) | ||
134 | { | ||
145 | return None; | 135 | return None; |
146 | } | 136 | } |
137 | |||
147 | let contents = read(&path); | 138 | let contents = read(&path); |
148 | Some((path, contents)) | 139 | Some((path, contents)) |
149 | }) | 140 | }) |
@@ -170,43 +161,42 @@ impl NotifyActor { | |||
170 | (file, contents) | 161 | (file, contents) |
171 | }) | 162 | }) |
172 | .collect::<Vec<_>>(), | 163 | .collect::<Vec<_>>(), |
173 | loader::Entry::Directory { path, include } => { | 164 | loader::Entry::Directories(dirs) => { |
174 | let include = Include::new(include); | 165 | let mut res = Vec::new(); |
175 | self.config.push((path.clone(), include.clone(), watch)); | 166 | |
176 | 167 | for root in dirs.include.iter() { | |
177 | let files = WalkDir::new(&path) | 168 | let walkdir = WalkDir::new(root).into_iter().filter_entry(|entry| { |
178 | .into_iter() | 169 | if !entry.file_type().is_dir() { |
179 | .filter_entry(|entry| { | 170 | return true; |
180 | let abs_path: &AbsPath = entry.path().try_into().unwrap(); | ||
181 | match abs_path.strip_prefix(&path) { | ||
182 | Some(rel_path) => { | ||
183 | !(entry.file_type().is_dir() && include.exclude_dir(rel_path)) | ||
184 | } | ||
185 | None => false, | ||
186 | } | 171 | } |
187 | }) | 172 | let path = AbsPath::assert(entry.path()); |
188 | .filter_map(|entry| entry.ok()) | 173 | root == path |
189 | .filter_map(|entry| { | 174 | || dirs.exclude.iter().chain(&dirs.include).all(|it| it != path) |
175 | }); | ||
176 | |||
177 | let files = walkdir.filter_map(|it| it.ok()).filter_map(|entry| { | ||
190 | let is_dir = entry.file_type().is_dir(); | 178 | let is_dir = entry.file_type().is_dir(); |
191 | let is_file = entry.file_type().is_file(); | 179 | let is_file = entry.file_type().is_file(); |
192 | let abs_path = AbsPathBuf::try_from(entry.into_path()).unwrap(); | 180 | let abs_path = AbsPathBuf::assert(entry.into_path()); |
193 | if is_dir && watch { | 181 | if is_dir && watch { |
194 | self.watch(abs_path.clone()); | 182 | self.watch(abs_path.clone()); |
195 | } | 183 | } |
196 | let rel_path = abs_path.strip_prefix(&path)?; | 184 | if !is_file { |
197 | if is_file && include.include_file(&rel_path) { | 185 | return None; |
198 | Some(abs_path) | 186 | } |
199 | } else { | 187 | let ext = abs_path.extension().unwrap_or_default(); |
200 | None | 188 | if dirs.extensions.iter().all(|it| it.as_str() != ext) { |
189 | return None; | ||
201 | } | 190 | } |
191 | Some(abs_path) | ||
202 | }); | 192 | }); |
203 | 193 | ||
204 | files | 194 | res.extend(files.map(|file| { |
205 | .map(|file| { | ||
206 | let contents = read(file.as_path()); | 195 | let contents = read(file.as_path()); |
207 | (file, contents) | 196 | (file, contents) |
208 | }) | 197 | })); |
209 | .collect() | 198 | } |
199 | res | ||
210 | } | 200 | } |
211 | } | 201 | } |
212 | } | 202 | } |