1use crate::{DrivenError, Result};
4use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
5use std::path::Path;
6use std::sync::mpsc::{Receiver, channel};
7
8#[derive(Debug)]
10pub struct FileWatcher {
11 _watcher: RecommendedWatcher,
13 rx: Receiver<notify::Result<notify::Event>>,
15}
16
17impl FileWatcher {
18 pub fn new(path: &Path) -> Result<Self> {
20 let (tx, rx) = channel();
21
22 let mut watcher = RecommendedWatcher::new(
23 move |res| {
24 let _ = tx.send(res);
25 },
26 Config::default(),
27 )
28 .map_err(|e| DrivenError::Sync(format!("Failed to create watcher: {}", e)))?;
29
30 watcher
31 .watch(path, RecursiveMode::Recursive)
32 .map_err(|e| DrivenError::Sync(format!("Failed to watch path: {}", e)))?;
33
34 Ok(Self {
35 _watcher: watcher,
36 rx,
37 })
38 }
39
40 pub fn pending_events(&self) -> Vec<WatchEvent> {
42 let mut events = Vec::new();
43
44 while let Ok(result) = self.rx.try_recv() {
45 if let Ok(event) = result {
46 events.push(WatchEvent::from_notify(event));
47 }
48 }
49
50 events
51 }
52
53 pub fn wait_for_event(&self) -> Option<WatchEvent> {
55 self.rx
56 .recv()
57 .ok()
58 .and_then(|r| r.ok())
59 .map(WatchEvent::from_notify)
60 }
61}
62
63#[derive(Debug, Clone)]
65pub struct WatchEvent {
66 pub kind: WatchEventKind,
68 pub paths: Vec<std::path::PathBuf>,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum WatchEventKind {
75 Create,
77 Modify,
79 Remove,
81 Other,
83}
84
85impl WatchEvent {
86 fn from_notify(event: notify::Event) -> Self {
87 let kind = match event.kind {
88 notify::EventKind::Create(_) => WatchEventKind::Create,
89 notify::EventKind::Modify(_) => WatchEventKind::Modify,
90 notify::EventKind::Remove(_) => WatchEventKind::Remove,
91 _ => WatchEventKind::Other,
92 };
93
94 Self {
95 kind,
96 paths: event.paths,
97 }
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn test_watch_event_kind() {
107 assert_ne!(WatchEventKind::Create, WatchEventKind::Modify);
108 }
109}