diff options
Diffstat (limited to 'crates/ra_vfs/src/io')
-rw-r--r-- | crates/ra_vfs/src/io/mod.rs | 45 | ||||
-rw-r--r-- | crates/ra_vfs/src/io/watcher.rs | 16 |
2 files changed, 40 insertions, 21 deletions
diff --git a/crates/ra_vfs/src/io/mod.rs b/crates/ra_vfs/src/io/mod.rs index 6d5af7690..daac6c6f2 100644 --- a/crates/ra_vfs/src/io/mod.rs +++ b/crates/ra_vfs/src/io/mod.rs | |||
@@ -9,26 +9,27 @@ use crossbeam_channel::{Receiver, Sender}; | |||
9 | use parking_lot::Mutex; | 9 | use parking_lot::Mutex; |
10 | use relative_path::RelativePathBuf; | 10 | use relative_path::RelativePathBuf; |
11 | use thread_worker::WorkerHandle; | 11 | use thread_worker::WorkerHandle; |
12 | use walkdir::{DirEntry, WalkDir}; | 12 | use walkdir::WalkDir; |
13 | 13 | ||
14 | mod watcher; | 14 | mod watcher; |
15 | use watcher::Watcher; | 15 | use watcher::Watcher; |
16 | pub use watcher::WatcherChange; | 16 | pub use watcher::WatcherChange; |
17 | 17 | ||
18 | use crate::VfsRoot; | 18 | use crate::{RootFilter, VfsRoot}; |
19 | 19 | ||
20 | pub(crate) enum Task { | 20 | pub(crate) enum Task { |
21 | AddRoot { | 21 | AddRoot { |
22 | root: VfsRoot, | 22 | root: VfsRoot, |
23 | path: PathBuf, | 23 | path: PathBuf, |
24 | filter: Box<Fn(&DirEntry) -> bool + Send>, | 24 | root_filter: Arc<RootFilter>, |
25 | nested_roots: Vec<PathBuf>, | ||
25 | }, | 26 | }, |
26 | /// this variant should only be created by the watcher | 27 | /// this variant should only be created by the watcher |
27 | HandleChange(WatcherChange), | 28 | HandleChange(WatcherChange), |
28 | LoadChange(WatcherChange), | 29 | LoadChange(WatcherChange), |
29 | Watch { | 30 | Watch { |
30 | dir: PathBuf, | 31 | dir: PathBuf, |
31 | filter: Box<Fn(&DirEntry) -> bool + Send>, | 32 | root_filter: Arc<RootFilter>, |
32 | }, | 33 | }, |
33 | } | 34 | } |
34 | 35 | ||
@@ -109,7 +110,7 @@ impl Worker { | |||
109 | fn watch( | 110 | fn watch( |
110 | watcher: &Arc<Mutex<Option<Watcher>>>, | 111 | watcher: &Arc<Mutex<Option<Watcher>>>, |
111 | dir: &Path, | 112 | dir: &Path, |
112 | filter_entry: impl Fn(&DirEntry) -> bool, | 113 | filter_entry: &RootFilter, |
113 | emit_for_existing: bool, | 114 | emit_for_existing: bool, |
114 | ) { | 115 | ) { |
115 | let mut watcher = watcher.lock(); | 116 | let mut watcher = watcher.lock(); |
@@ -125,10 +126,19 @@ fn watch( | |||
125 | 126 | ||
126 | fn handle_task(task: Task, watcher: &Arc<Mutex<Option<Watcher>>>) -> TaskResult { | 127 | fn handle_task(task: Task, watcher: &Arc<Mutex<Option<Watcher>>>) -> TaskResult { |
127 | match task { | 128 | match task { |
128 | Task::AddRoot { root, path, filter } => { | 129 | Task::AddRoot { |
129 | watch(watcher, &path, &*filter, false); | 130 | root, |
131 | path, | ||
132 | root_filter, | ||
133 | nested_roots, | ||
134 | } => { | ||
135 | watch(watcher, &path, &*root_filter, false); | ||
130 | log::debug!("loading {} ...", path.as_path().display()); | 136 | log::debug!("loading {} ...", path.as_path().display()); |
131 | let files = load_root(path.as_path(), &*filter); | 137 | let files = load_root( |
138 | path.as_path(), | ||
139 | root_filter.as_ref(), | ||
140 | nested_roots.as_slice(), | ||
141 | ); | ||
132 | log::debug!("... loaded {}", path.as_path().display()); | 142 | log::debug!("... loaded {}", path.as_path().display()); |
133 | TaskResult::AddRoot(AddRootResult { root, files }) | 143 | TaskResult::AddRoot(AddRootResult { root, files }) |
134 | } | 144 | } |
@@ -143,16 +153,27 @@ fn handle_task(task: Task, watcher: &Arc<Mutex<Option<Watcher>>>) -> TaskResult | |||
143 | None => TaskResult::NoOp, | 153 | None => TaskResult::NoOp, |
144 | } | 154 | } |
145 | } | 155 | } |
146 | Task::Watch { dir, filter } => { | 156 | Task::Watch { dir, root_filter } => { |
147 | watch(watcher, &dir, &*filter, true); | 157 | watch(watcher, &dir, root_filter.as_ref(), true); |
148 | TaskResult::NoOp | 158 | TaskResult::NoOp |
149 | } | 159 | } |
150 | } | 160 | } |
151 | } | 161 | } |
152 | 162 | ||
153 | fn load_root(root: &Path, filter: &dyn Fn(&DirEntry) -> bool) -> Vec<(RelativePathBuf, String)> { | 163 | fn load_root( |
164 | root: &Path, | ||
165 | root_filter: &RootFilter, | ||
166 | nested_roots: &[PathBuf], | ||
167 | ) -> Vec<(RelativePathBuf, String)> { | ||
154 | let mut res = Vec::new(); | 168 | let mut res = Vec::new(); |
155 | for entry in WalkDir::new(root).into_iter().filter_entry(filter) { | 169 | for entry in WalkDir::new(root).into_iter().filter_entry(|entry| { |
170 | if entry.file_type().is_dir() && nested_roots.iter().any(|it| it == entry.path()) { | ||
171 | // do not load files of a nested root | ||
172 | false | ||
173 | } else { | ||
174 | root_filter.can_contain(entry.path()).is_some() | ||
175 | } | ||
176 | }) { | ||
156 | let entry = match entry { | 177 | let entry = match entry { |
157 | Ok(entry) => entry, | 178 | Ok(entry) => entry, |
158 | Err(e) => { | 179 | Err(e) => { |
diff --git a/crates/ra_vfs/src/io/watcher.rs b/crates/ra_vfs/src/io/watcher.rs index e33298477..5e9bc8ff3 100644 --- a/crates/ra_vfs/src/io/watcher.rs +++ b/crates/ra_vfs/src/io/watcher.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use crate::io; | 1 | use crate::{io, RootFilter}; |
2 | use crossbeam_channel::Sender; | 2 | use crossbeam_channel::Sender; |
3 | use drop_bomb::DropBomb; | 3 | use drop_bomb::DropBomb; |
4 | use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; | 4 | use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; |
@@ -8,7 +8,7 @@ use std::{ | |||
8 | thread, | 8 | thread, |
9 | time::Duration, | 9 | time::Duration, |
10 | }; | 10 | }; |
11 | use walkdir::{DirEntry, WalkDir}; | 11 | use walkdir::WalkDir; |
12 | 12 | ||
13 | #[derive(Debug)] | 13 | #[derive(Debug)] |
14 | pub enum WatcherChange { | 14 | pub enum WatcherChange { |
@@ -83,13 +83,11 @@ impl Watcher { | |||
83 | }) | 83 | }) |
84 | } | 84 | } |
85 | 85 | ||
86 | pub fn watch_recursive( | 86 | pub fn watch_recursive(&mut self, dir: &Path, filter: &RootFilter, emit_for_contents: bool) { |
87 | &mut self, | 87 | for res in WalkDir::new(dir) |
88 | dir: &Path, | 88 | .into_iter() |
89 | filter_entry: impl Fn(&DirEntry) -> bool, | 89 | .filter_entry(|entry| filter.can_contain(entry.path()).is_some()) |
90 | emit_for_contents: bool, | 90 | { |
91 | ) { | ||
92 | for res in WalkDir::new(dir).into_iter().filter_entry(filter_entry) { | ||
93 | match res { | 91 | match res { |
94 | Ok(entry) => { | 92 | Ok(entry) => { |
95 | if entry.path().is_dir() { | 93 | if entry.path().is_dir() { |