142 lines
5.1 KiB
Rust
142 lines
5.1 KiB
Rust
use crate::options::structs::{CustomError, Files};
|
|
use crate::utils::prcs::{is_active, is_frozen};
|
|
use inotify::{EventMask, Inotify, WatchMask};
|
|
use std::borrow::BorrowMut;
|
|
use std::path::Path;
|
|
use std::sync::Arc;
|
|
use tokio::sync::mpsc;
|
|
use tokio::time::Duration;
|
|
|
|
pub async fn create_watcher(filename: &str, path: &str) -> Result<Inotify, std::io::Error> {
|
|
let src = format!("{}{}", path, filename);
|
|
let inotify: Inotify = Inotify::init()?;
|
|
inotify.watches().add(&src, WatchMask::ALL_EVENTS)?;
|
|
Ok(inotify)
|
|
}
|
|
|
|
pub async fn file_handler(
|
|
name: &str,
|
|
files: &[Files],
|
|
tx: Arc<mpsc::Sender<u8>>,
|
|
watchers: Arc<tokio::sync::Mutex<Vec<Inotify>>>,
|
|
) -> Result<(), CustomError> {
|
|
for (i, file) in files.iter().enumerate() {
|
|
// let src = format!("{}{}", file.src, file.filename);
|
|
if check_file(&file.filename, &file.src).await.is_err() {
|
|
if !is_active(name).await || is_frozen(name).await {
|
|
return Err(CustomError::Fatal);
|
|
}
|
|
match file.triggers.on_delete.as_str() {
|
|
"stay" => {
|
|
tx.send(9).await.unwrap();
|
|
continue;
|
|
}
|
|
"stop" => {
|
|
if is_active(name).await {
|
|
tx.send(1).await.unwrap();
|
|
}
|
|
return Err(CustomError::Fatal);
|
|
}
|
|
"hold" => {
|
|
if is_active(name).await {
|
|
tx.send(2).await.unwrap();
|
|
return Err(CustomError::Fatal);
|
|
}
|
|
}
|
|
_ => {
|
|
tokio::time::sleep(Duration::from_millis(50)).await;
|
|
tx.send(101).await.unwrap();
|
|
return Err(CustomError::Fatal);
|
|
}
|
|
}
|
|
} else if is_active(name).await && !is_frozen(name).await {
|
|
let watchers = watchers.clone();
|
|
// println!("mutex: {:?}", watchers);
|
|
let mut buffer = [0; 128];
|
|
let mut mutex_guard = watchers.lock().await;
|
|
if let Some(notify) = mutex_guard.get_mut(i) {
|
|
let events = notify.read_events(&mut buffer);
|
|
// println!("{:?}", events);
|
|
if events.is_ok() {
|
|
let events: Vec<EventMask> = events
|
|
.unwrap()
|
|
.map(|mask| mask.mask)
|
|
.filter(|mask| {
|
|
*mask == EventMask::MODIFY || *mask == EventMask::DELETE_SELF
|
|
})
|
|
.collect();
|
|
for event in events {
|
|
if let EventMask::DELETE_SELF = event {
|
|
// ! warning (DELETE_SELF event) !
|
|
// println!("! warning (DELETE_SELF event) !");
|
|
// * watcher recreation after dealing with file recreation mechanism in text editors
|
|
let mutex = notify.borrow_mut();
|
|
|
|
*mutex = create_watcher(&file.filename, &file.src).await.unwrap();
|
|
}
|
|
match file.triggers.on_change.as_str() {
|
|
"stop" => {
|
|
let _ = tx.send(7).await;
|
|
}
|
|
"restart" => {
|
|
let _ = tx.send(8).await;
|
|
}
|
|
"stay" => {
|
|
let _ = tx.send(9).await;
|
|
}
|
|
_ => {
|
|
let _ = tx.send(101).await;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tokio::task::yield_now().await;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn check_file(filename: &str, path: &str) -> Result<(), CustomError> {
|
|
let arc_name = Arc::new(filename.to_string());
|
|
let arc_path = Arc::new(path.to_string());
|
|
tokio::task::spawn_blocking(move || {
|
|
let file_concat = format!("{}{}", arc_path, arc_name);
|
|
let path = Path::new(&file_concat);
|
|
if path.exists() {
|
|
Ok(())
|
|
} else {
|
|
Err(CustomError::Fatal)
|
|
}
|
|
})
|
|
.await
|
|
.unwrap_or_else(|_| {
|
|
panic!("Corrupted while file check process");
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod files_unittests {
|
|
use super::*;
|
|
#[tokio::test]
|
|
async fn try_to_create_watcher() {
|
|
let res = create_watcher("dep-file", "/home/user/monitor/runner-rs/tests/examples/").await;
|
|
assert!(res.is_ok());
|
|
}
|
|
#[tokio::test]
|
|
async fn try_to_create_invalid_watcher() {
|
|
let res = create_watcher("invalid-file", "/path/to/the/hell").await;
|
|
assert!(res.is_err());
|
|
}
|
|
#[tokio::test]
|
|
async fn check_existing_file() {
|
|
let res = check_file("dep-file", "/home/user/monitor/runner-rs/tests/examples/").await;
|
|
assert!(res.is_ok());
|
|
}
|
|
#[tokio::test]
|
|
async fn check_non_existing_file() {
|
|
let res = check_file("invalid-file", "/path/to/the/hell").await;
|
|
assert!(res.is_err());
|
|
}
|
|
}
|