userd 0.2.0

A user daemon, managing services and regular running of jobs, in user space.
use notify::{
    Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher,
    event::{AccessKind, AccessMode},
};
use std::path::Path;
use tokio::sync::mpsc::{Receiver, channel};

fn async_watcher() -> notify::Result<(RecommendedWatcher, Receiver<notify::Result<Event>>)> {
    let (tx, rx) = channel(1);

    // Automatically select the best implementation for your platform.
    // You can also access each implementation directly e.g. INotifyWatcher.
    let tokio_runtime = tokio::runtime::Handle::current();
    let watcher = RecommendedWatcher::new(
        move |res| {
            let tx = tx.clone();
            tokio_runtime.spawn(async move {
                if let Err(e) = tx.send(res).await {
                    log::error!("error: {}", e);
                }
            });
        },
        Config::default(),
    )?;

    Ok((watcher, rx))
}

pub async fn async_watch<P: AsRef<Path>>(path: P) -> notify::Result<()> {
    let (mut watcher, mut rx) = async_watcher()?;

    // Add a path to be watched. All files and directories at that path and
    // below will be monitored for changes.
    watcher.watch(path.as_ref(), RecursiveMode::Recursive)?;

    while let Some(res) = rx.recv().await {
        match res {
            Ok(event) => {
                if let EventKind::Access(kind) = event.kind
                    && let AccessKind::Close(AccessMode::Write) = kind
                {
                    return Ok(());
                }
            }
            Err(e) => log::error!("watch error: {:?}", e),
        }
    }

    Ok(())
}