1use std::path::PathBuf;
2use std::sync::mpsc::Sender;
3use std::sync::mpsc::{channel, Receiver};
4
5use anyhow::Result;
6use notify::{Event, EventHandler, Watcher};
7
8use crate::{WaitOptions, Waitable};
9
10#[derive(Clone)]
11pub struct FileWaiter {
12 pub path: PathBuf,
13}
14
15impl FileWaiter {
16 pub fn new(path: PathBuf) -> Self {
17 Self { path }
18 }
19}
20
21impl Waitable for FileWaiter {
22 async fn wait(&self, _: &WaitOptions) -> Result<()> {
23 let (file_exists_handler, rx) = FileExistsHandler::new();
24 let mut watcher = notify::recommended_watcher(file_exists_handler)?;
25
26 if let Some(parent) = self.path.parent() {
27 watcher.watch(parent, notify::RecursiveMode::NonRecursive)?;
28
29 if rx.recv().is_ok() {
30 watcher.unwatch(parent)?;
31 }
32 } else {
33 watcher.watch(&self.path, notify::RecursiveMode::NonRecursive)?;
34
35 if rx.recv().is_ok() {
36 watcher.unwatch(&self.path)?;
37 }
38 }
39
40 Ok(())
41 }
42}
43
44struct FileExistsHandler {
45 tx: Sender<()>,
46}
47
48impl FileExistsHandler {
49 pub fn new() -> (Self, Receiver<()>) {
50 let (tx, rx) = channel();
51
52 (Self { tx }, rx)
53 }
54}
55
56impl EventHandler for FileExistsHandler {
57 fn handle_event(&mut self, event: notify::Result<Event>) {
58 if let Ok(event) = event {
59 if let notify::EventKind::Create(_) = event.kind {
60 self.tx.send(()).expect("Channel dropped.");
61 }
62 }
63 }
64}