avoid boxing
This commit is contained in:
parent
277e0f1baa
commit
2a1afad3ed
@ -9,26 +9,27 @@ use crossbeam_channel::{Receiver, Sender};
|
||||
use parking_lot::Mutex;
|
||||
use relative_path::RelativePathBuf;
|
||||
use thread_worker::WorkerHandle;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
mod watcher;
|
||||
use watcher::Watcher;
|
||||
pub use watcher::WatcherChange;
|
||||
|
||||
use crate::VfsRoot;
|
||||
use crate::{RootFilter, VfsRoot};
|
||||
|
||||
pub(crate) enum Task {
|
||||
AddRoot {
|
||||
root: VfsRoot,
|
||||
path: PathBuf,
|
||||
filter: Box<Fn(&DirEntry) -> bool + Send>,
|
||||
root_filter: Arc<RootFilter>,
|
||||
nested_roots: Vec<PathBuf>,
|
||||
},
|
||||
/// this variant should only be created by the watcher
|
||||
HandleChange(WatcherChange),
|
||||
LoadChange(WatcherChange),
|
||||
Watch {
|
||||
dir: PathBuf,
|
||||
filter: Box<Fn(&DirEntry) -> bool + Send>,
|
||||
root_filter: Arc<RootFilter>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -109,7 +110,7 @@ impl Worker {
|
||||
fn watch(
|
||||
watcher: &Arc<Mutex<Option<Watcher>>>,
|
||||
dir: &Path,
|
||||
filter_entry: impl Fn(&DirEntry) -> bool,
|
||||
filter_entry: &RootFilter,
|
||||
emit_for_existing: bool,
|
||||
) {
|
||||
let mut watcher = watcher.lock();
|
||||
@ -125,10 +126,19 @@ fn watch(
|
||||
|
||||
fn handle_task(task: Task, watcher: &Arc<Mutex<Option<Watcher>>>) -> TaskResult {
|
||||
match task {
|
||||
Task::AddRoot { root, path, filter } => {
|
||||
watch(watcher, &path, &*filter, false);
|
||||
Task::AddRoot {
|
||||
root,
|
||||
path,
|
||||
root_filter,
|
||||
nested_roots,
|
||||
} => {
|
||||
watch(watcher, &path, &*root_filter, false);
|
||||
log::debug!("loading {} ...", path.as_path().display());
|
||||
let files = load_root(path.as_path(), &*filter);
|
||||
let files = load_root(
|
||||
path.as_path(),
|
||||
root_filter.as_ref(),
|
||||
nested_roots.as_slice(),
|
||||
);
|
||||
log::debug!("... loaded {}", path.as_path().display());
|
||||
TaskResult::AddRoot(AddRootResult { root, files })
|
||||
}
|
||||
@ -143,16 +153,27 @@ fn handle_task(task: Task, watcher: &Arc<Mutex<Option<Watcher>>>) -> TaskResult
|
||||
None => TaskResult::NoOp,
|
||||
}
|
||||
}
|
||||
Task::Watch { dir, filter } => {
|
||||
watch(watcher, &dir, &*filter, true);
|
||||
Task::Watch { dir, root_filter } => {
|
||||
watch(watcher, &dir, root_filter.as_ref(), true);
|
||||
TaskResult::NoOp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_root(root: &Path, filter: &dyn Fn(&DirEntry) -> bool) -> Vec<(RelativePathBuf, String)> {
|
||||
fn load_root(
|
||||
root: &Path,
|
||||
root_filter: &RootFilter,
|
||||
nested_roots: &[PathBuf],
|
||||
) -> Vec<(RelativePathBuf, String)> {
|
||||
let mut res = Vec::new();
|
||||
for entry in WalkDir::new(root).into_iter().filter_entry(filter) {
|
||||
for entry in WalkDir::new(root).into_iter().filter_entry(|entry| {
|
||||
if entry.file_type().is_dir() && nested_roots.iter().any(|it| it == entry.path()) {
|
||||
// do not load files of a nested root
|
||||
false
|
||||
} else {
|
||||
root_filter.can_contain(entry.path()).is_some()
|
||||
}
|
||||
}) {
|
||||
let entry = match entry {
|
||||
Ok(entry) => entry,
|
||||
Err(e) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::io;
|
||||
use crate::{io, RootFilter};
|
||||
use crossbeam_channel::Sender;
|
||||
use drop_bomb::DropBomb;
|
||||
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher};
|
||||
@ -8,7 +8,7 @@ use std::{
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WatcherChange {
|
||||
@ -83,13 +83,11 @@ impl Watcher {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn watch_recursive(
|
||||
&mut self,
|
||||
dir: &Path,
|
||||
filter_entry: impl Fn(&DirEntry) -> bool,
|
||||
emit_for_contents: bool,
|
||||
) {
|
||||
for res in WalkDir::new(dir).into_iter().filter_entry(filter_entry) {
|
||||
pub fn watch_recursive(&mut self, dir: &Path, filter: &RootFilter, emit_for_contents: bool) {
|
||||
for res in WalkDir::new(dir)
|
||||
.into_iter()
|
||||
.filter_entry(|entry| filter.can_contain(entry.path()).is_some())
|
||||
{
|
||||
match res {
|
||||
Ok(entry) => {
|
||||
if entry.path().is_dir() {
|
||||
|
@ -28,7 +28,6 @@ use crossbeam_channel::Receiver;
|
||||
use ra_arena::{impl_arena_id, Arena, RawId};
|
||||
use relative_path::RelativePathBuf;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use walkdir::DirEntry;
|
||||
|
||||
pub use crate::io::TaskResult as VfsTask;
|
||||
use io::{Task, TaskResult, WatcherChange, WatcherChangeData, Worker};
|
||||
@ -128,23 +127,17 @@ impl Vfs {
|
||||
let root = res.roots.alloc(root_filter.clone());
|
||||
res.root2files.insert(root, Default::default());
|
||||
|
||||
let nested = roots[..i]
|
||||
let nested_roots = roots[..i]
|
||||
.iter()
|
||||
.filter(|it| it.starts_with(path))
|
||||
.map(|it| it.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let filter = move |entry: &DirEntry| {
|
||||
if entry.file_type().is_dir() && nested.iter().any(|it| it == entry.path()) {
|
||||
false
|
||||
} else {
|
||||
root_filter.can_contain(entry.path()).is_some()
|
||||
}
|
||||
};
|
||||
let task = io::Task::AddRoot {
|
||||
root,
|
||||
path: path.clone(),
|
||||
filter: Box::new(filter),
|
||||
root_filter,
|
||||
nested_roots,
|
||||
};
|
||||
res.worker.sender().send(task).unwrap();
|
||||
}
|
||||
@ -232,13 +225,11 @@ impl Vfs {
|
||||
WatcherChange::Create(path) if path.is_dir() => {
|
||||
if let Some((root, _path, _file)) = self.find_root(&path) {
|
||||
let root_filter = self.roots[root].clone();
|
||||
let filter =
|
||||
move |entry: &DirEntry| root_filter.can_contain(entry.path()).is_some();
|
||||
self.worker
|
||||
.sender()
|
||||
.send(Task::Watch {
|
||||
dir: path.to_path_buf(),
|
||||
filter: Box::new(filter),
|
||||
root_filter,
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user