aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_vfs/src/io
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_vfs/src/io')
-rw-r--r--crates/ra_vfs/src/io/mod.rs45
-rw-r--r--crates/ra_vfs/src/io/watcher.rs16
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};
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() {