aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_vfs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_vfs')
-rw-r--r--crates/ra_vfs/src/io/mod.rs45
-rw-r--r--crates/ra_vfs/src/io/watcher.rs16
-rw-r--r--crates/ra_vfs/src/lib.rs17
3 files changed, 44 insertions, 34 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};
9use parking_lot::Mutex; 9use parking_lot::Mutex;
10use relative_path::RelativePathBuf; 10use relative_path::RelativePathBuf;
11use thread_worker::WorkerHandle; 11use thread_worker::WorkerHandle;
12use walkdir::{DirEntry, WalkDir}; 12use walkdir::WalkDir;
13 13
14mod watcher; 14mod watcher;
15use watcher::Watcher; 15use watcher::Watcher;
16pub use watcher::WatcherChange; 16pub use watcher::WatcherChange;
17 17
18use crate::VfsRoot; 18use crate::{RootFilter, VfsRoot};
19 19
20pub(crate) enum Task { 20pub(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 {
109fn watch( 110fn 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
126fn handle_task(task: Task, watcher: &Arc<Mutex<Option<Watcher>>>) -> TaskResult { 127fn 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
153fn load_root(root: &Path, filter: &dyn Fn(&DirEntry) -> bool) -> Vec<(RelativePathBuf, String)> { 163fn 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 @@
1use crate::io; 1use crate::{io, RootFilter};
2use crossbeam_channel::Sender; 2use crossbeam_channel::Sender;
3use drop_bomb::DropBomb; 3use drop_bomb::DropBomb;
4use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher}; 4use 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};
11use walkdir::{DirEntry, WalkDir}; 11use walkdir::WalkDir;
12 12
13#[derive(Debug)] 13#[derive(Debug)]
14pub enum WatcherChange { 14pub 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() {
diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs
index 5db0d8646..1d0af6a09 100644
--- a/crates/ra_vfs/src/lib.rs
+++ b/crates/ra_vfs/src/lib.rs
@@ -28,7 +28,6 @@ use crossbeam_channel::Receiver;
28use ra_arena::{impl_arena_id, Arena, RawId}; 28use ra_arena::{impl_arena_id, Arena, RawId};
29use relative_path::RelativePathBuf; 29use relative_path::RelativePathBuf;
30use rustc_hash::{FxHashMap, FxHashSet}; 30use rustc_hash::{FxHashMap, FxHashSet};
31use walkdir::DirEntry;
32 31
33pub use crate::io::TaskResult as VfsTask; 32pub use crate::io::TaskResult as VfsTask;
34use io::{Task, TaskResult, WatcherChange, WatcherChangeData, Worker}; 33use io::{Task, TaskResult, WatcherChange, WatcherChangeData, Worker};
@@ -128,23 +127,17 @@ impl Vfs {
128 let root = res.roots.alloc(root_filter.clone()); 127 let root = res.roots.alloc(root_filter.clone());
129 res.root2files.insert(root, Default::default()); 128 res.root2files.insert(root, Default::default());
130 129
131 let nested = roots[..i] 130 let nested_roots = roots[..i]
132 .iter() 131 .iter()
133 .filter(|it| it.starts_with(path)) 132 .filter(|it| it.starts_with(path))
134 .map(|it| it.clone()) 133 .map(|it| it.clone())
135 .collect::<Vec<_>>(); 134 .collect::<Vec<_>>();
136 135
137 let filter = move |entry: &DirEntry| {
138 if entry.file_type().is_dir() && nested.iter().any(|it| it == entry.path()) {
139 false
140 } else {
141 root_filter.can_contain(entry.path()).is_some()
142 }
143 };
144 let task = io::Task::AddRoot { 136 let task = io::Task::AddRoot {
145 root, 137 root,
146 path: path.clone(), 138 path: path.clone(),
147 filter: Box::new(filter), 139 root_filter,
140 nested_roots,
148 }; 141 };
149 res.worker.sender().send(task).unwrap(); 142 res.worker.sender().send(task).unwrap();
150 } 143 }
@@ -232,13 +225,11 @@ impl Vfs {
232 WatcherChange::Create(path) if path.is_dir() => { 225 WatcherChange::Create(path) if path.is_dir() => {
233 if let Some((root, _path, _file)) = self.find_root(&path) { 226 if let Some((root, _path, _file)) = self.find_root(&path) {
234 let root_filter = self.roots[root].clone(); 227 let root_filter = self.roots[root].clone();
235 let filter =
236 move |entry: &DirEntry| root_filter.can_contain(entry.path()).is_some();
237 self.worker 228 self.worker
238 .sender() 229 .sender()
239 .send(Task::Watch { 230 .send(Task::Watch {
240 dir: path.to_path_buf(), 231 dir: path.to_path_buf(),
241 filter: Box::new(filter), 232 root_filter,
242 }) 233 })
243 .unwrap() 234 .unwrap()
244 } 235 }