implement more robust file watcher

This commit is contained in:
2022-01-29 15:22:14 +01:00
parent 381eaf970f
commit f21497dd2e
6 changed files with 93 additions and 104 deletions

70
src/filewatcher.rs Normal file
View File

@@ -0,0 +1,70 @@
use anyhow::{bail, Result};
use notify::{DebouncedEvent, Watcher, RecommendedWatcher};
use std::{
collections::BTreeSet,
path::{Path, PathBuf},
sync::mpsc,
time::Duration,
};
pub struct FileWatcher {
_watcher: RecommendedWatcher,
watched_files: BTreeSet<PathBuf>,
rx: mpsc::Receiver<DebouncedEvent>,
}
pub struct FileWatcherBuilder(BTreeSet<PathBuf>);
impl FileWatcher {
pub fn builder() -> FileWatcherBuilder {
FileWatcherBuilder(BTreeSet::new())
}
pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> {
let event = self.rx.try_recv();
match event {
Ok(DebouncedEvent::Create(path) | DebouncedEvent::Write(path)) => {
let handle = same_file::Handle::from_path(&path)?;
for file in &self.watched_files {
if handle == same_file::Handle::from_path(file)? {
return Ok(Some(path));
}
}
}
Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"),
_ => (),
}
Ok(None)
}
}
impl FileWatcherBuilder {
pub fn add_file<P: Into<PathBuf>>(&mut self, path: P) -> &mut Self {
self.0.insert(path.into());
self
}
pub fn build(self) -> Result<FileWatcher> {
let mut directories: BTreeSet<&Path> = BTreeSet::new();
for file in &self.0 {
if let Some(directory) = file.parent() {
directories.insert(directory);
}
}
let (tx, rx) = mpsc::channel();
let mut watcher = notify::watcher(tx, Duration::from_millis(100))?;
for directory in directories {
watcher.watch(directory, notify::RecursiveMode::NonRecursive)?;
}
Ok(FileWatcher {
_watcher: watcher,
watched_files: self.0,
rx,
})
}
}

View File

@@ -10,6 +10,10 @@ use wasmtime::{
Engine, GlobalType, Memory, MemoryType, Module, Mutability, Store, TypedFunc, ValType,
};
mod filewatcher;
pub use filewatcher::FileWatcher;
static GAMEPAD_KEYS: &'static [Key] = &[
Key::Up,
Key::Down,

View File

@@ -1,17 +1,14 @@
use std::fs::File;
use std::io::prelude::*;
use std::process;
use std::sync::mpsc;
use std::time::Duration;
use std::{
path::{Path, PathBuf},
process::exit,
};
use anyhow::{bail, Result};
use notify::{DebouncedEvent, Watcher};
use anyhow::Result;
use pico_args::Arguments;
use uw8::MicroW8;
use uw8::{FileWatcher, MicroW8};
fn main() -> Result<()> {
let mut args = Arguments::from_env();
@@ -72,13 +69,14 @@ fn run(mut args: Arguments) -> Result<()> {
uw8.set_timeout(timeout);
}
let (tx, rx) = mpsc::channel();
let mut watcher = notify::watcher(tx, Duration::from_millis(100))?;
let mut watcher = FileWatcher::builder();
if watch_mode {
watcher.watch(&filename, notify::RecursiveMode::NonRecursive)?;
watcher.add_file(&filename);
}
let watcher = watcher.build()?;
if let Err(err) = start_cart(&filename, &mut uw8, &config) {
eprintln!("Load error: {}", err);
if !watch_mode {
@@ -87,14 +85,10 @@ fn run(mut args: Arguments) -> Result<()> {
}
while uw8.is_open() {
match rx.try_recv() {
Ok(DebouncedEvent::Create(_) | DebouncedEvent::Write(_)) => {
if let Err(err) = start_cart(&filename, &mut uw8, &config) {
eprintln!("Load error: {}", err);
}
if watcher.poll_changed_file()?.is_some() {
if let Err(err) = start_cart(&filename, &mut uw8, &config) {
eprintln!("Load error: {}", err);
}
Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"),
_ => (),
}
if let Err(err) = uw8.run_frame() {