forked from rojo-rbx/rojo
Track watched paths in ImfsFetcher, exposed via ImfsDebug interface
This commit is contained in:
@@ -29,4 +29,9 @@ pub trait ImfsFetcher {
|
||||
fn watch(&mut self, path: &Path);
|
||||
fn unwatch(&mut self, path: &Path);
|
||||
fn receiver(&self) -> Receiver<ImfsEvent>;
|
||||
|
||||
/// A method intended for debugging what paths the fetcher is watching.
|
||||
fn watched_paths(&self) -> Vec<&Path> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,13 @@ use super::{
|
||||
/// Most operations return `ImfsEntry` objects to work around this, which is
|
||||
/// effectively a index into the `Imfs`.
|
||||
pub struct Imfs<F> {
|
||||
/// A hierarchical map from paths to items that have been read or partially
|
||||
/// read into memory by the Imfs.
|
||||
inner: PathMap<ImfsItem>,
|
||||
|
||||
/// This Imfs's fetcher, which is used for all actual interactions with the
|
||||
/// filesystem. It's referred to by the type parameter `F` all over, and is
|
||||
/// generic in order to make it feasible to mock.
|
||||
fetcher: F,
|
||||
}
|
||||
|
||||
@@ -270,9 +276,10 @@ pub trait ImfsDebug {
|
||||
fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>;
|
||||
fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>;
|
||||
fn debug_orphans(&self) -> Vec<&Path>;
|
||||
fn debug_watched_paths(&self) -> Vec<&Path>;
|
||||
}
|
||||
|
||||
impl<F> ImfsDebug for Imfs<F> {
|
||||
impl<F: ImfsFetcher> ImfsDebug for Imfs<F> {
|
||||
fn debug_load_snapshot<P: AsRef<Path>>(&mut self, path: P, snapshot: ImfsSnapshot) {
|
||||
let path = path.as_ref();
|
||||
|
||||
@@ -328,6 +335,10 @@ impl<F> ImfsDebug for Imfs<F> {
|
||||
fn debug_orphans(&self) -> Vec<&Path> {
|
||||
self.inner.orphans().collect()
|
||||
}
|
||||
|
||||
fn debug_watched_paths(&self) -> Vec<&Path> {
|
||||
self.fetcher.watched_paths()
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to file or folder in an `Imfs`. Can only be produced by the
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//! std::fs interface and notify as the file watcher.
|
||||
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fs, io,
|
||||
path::{Path, PathBuf},
|
||||
sync::mpsc,
|
||||
@@ -35,7 +36,13 @@ pub struct RealFetcher {
|
||||
/// Thread handle to convert notify's mpsc channel messages into
|
||||
/// crossbeam_channel messages.
|
||||
_converter_thread: JoinHandle<()>,
|
||||
|
||||
/// The crossbeam receiver filled with events from the converter thread.
|
||||
receiver: Receiver<ImfsEvent>,
|
||||
|
||||
/// All of the paths that the fetcher is watching, tracked here because
|
||||
/// notify does not expose this information.
|
||||
watched_paths: HashSet<PathBuf>,
|
||||
}
|
||||
|
||||
impl RealFetcher {
|
||||
@@ -69,6 +76,7 @@ impl RealFetcher {
|
||||
watcher,
|
||||
_converter_thread: handle,
|
||||
receiver,
|
||||
watched_paths: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,8 +140,13 @@ impl ImfsFetcher for RealFetcher {
|
||||
log::trace!("Watching path {}", path.display());
|
||||
|
||||
if let Some(watcher) = self.watcher.as_mut() {
|
||||
if let Err(err) = watcher.watch(path, RecursiveMode::NonRecursive) {
|
||||
log::warn!("Couldn't watch path {}: {:?}", path.display(), err);
|
||||
match watcher.watch(path, RecursiveMode::NonRecursive) {
|
||||
Ok(_) => {
|
||||
self.watched_paths.insert(path.to_path_buf());
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Couldn't watch path {}: {:?}", path.display(), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,6 +155,11 @@ impl ImfsFetcher for RealFetcher {
|
||||
log::trace!("Stopped watching path {}", path.display());
|
||||
|
||||
if let Some(watcher) = self.watcher.as_mut() {
|
||||
// Remove the path from our watched paths regardless of the outcome
|
||||
// of notify's unwatch to ensure we drop old paths in the event of a
|
||||
// rename.
|
||||
self.watched_paths.remove(path);
|
||||
|
||||
if let Err(err) = watcher.unwatch(path) {
|
||||
log::warn!("Couldn't unwatch path {}: {:?}", path.display(), err);
|
||||
}
|
||||
@@ -151,4 +169,8 @@ impl ImfsFetcher for RealFetcher {
|
||||
fn receiver(&self) -> Receiver<ImfsEvent> {
|
||||
self.receiver.clone()
|
||||
}
|
||||
|
||||
fn watched_paths(&self) -> Vec<&Path> {
|
||||
self.watched_paths.iter().map(|v| v.as_path()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user