use futures::{FutureExt, future::BoxFuture};
use std::path::PathBuf;
use crate::prelude::*;
pub(crate) struct File {
filename: PathBuf,
negate: bool,
check: config::ContentCheck,
update_check: config::UpdateCheck,
last_content: ccutils::sync::ArcRwLock<String>,
}
impl File {
pub(crate) fn new(
filename: PathBuf,
negate: bool,
check: config::ContentCheck,
update_check: config::UpdateCheck,
) -> Self {
Self {
filename,
negate,
check,
update_check,
last_content: Default::default(),
}
}
}
impl super::Condition for File {
fn check(&self) -> BoxFuture<'static, Result<bool>> {
let content = std::fs::read_to_string(&self.filename);
let negate = self.negate;
let check = self.check.clone();
let last_content = self.last_content.clone();
async move {
let content = content?;
let r = match check {
config::ContentCheck::Contains { value } => content.contains(&value),
};
*last_content.write().unwrap() = content;
Ok(r != negate)
}
.boxed()
}
fn wait_for_change(&self) -> BoxFuture<'static, Result<()>> {
let filename = self.filename.clone();
let last_content = self.last_content.clone();
let update_check = self.update_check.clone();
async move {
loop {
match update_check {
config::UpdateCheck::Watch => {
utils::async_watch(filename.clone()).await?;
}
config::UpdateCheck::Every { duration } => {
tokio::time::sleep(duration).await;
}
}
let content = std::fs::read_to_string(&filename)?;
if content != *last_content.read().unwrap() {
log::info!(
"File {:?} content has changed from '{}' to '{}'.",
filename,
content,
last_content.read().unwrap()
);
break;
}
}
Ok(())
}
.boxed()
}
}