wait_on/resource/
file.rs

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}