use std::{collections::HashMap, path::Path, sync::Arc, time::Duration};
use tokio::task::JoinHandle;
use watchexec_events::{Event, FileType, ProcessEnd};
use watchexec_signals::Signal;
use watchexec_supervisor::{
command::Command,
job::{start_job, Job},
};
use crate::id::Id;
use super::QuitManner;
#[derive(Debug)]
pub struct Handler {
pub events: Arc<[Event]>,
extant: HashMap<Id, Job>,
pub(crate) new: HashMap<Id, (Job, JoinHandle<()>)>,
pub(crate) quit: Option<QuitManner>,
}
impl Handler {
pub(crate) fn new(events: Arc<[Event]>, jobs: HashMap<Id, Job>) -> Self {
Self {
events,
extant: jobs,
new: HashMap::new(),
quit: None,
}
}
pub fn create_job(&mut self, command: Arc<Command>) -> (Id, Job) {
let id = Id::default();
let (job, task) = start_job(command);
self.new.insert(id, (job.clone(), task));
(id, job)
}
fn create_job_with_id(&mut self, id: Id, command: Arc<Command>) -> Job {
let (job, task) = start_job(command);
self.new.insert(id, (job.clone(), task));
job
}
pub fn get_or_create_job(&mut self, id: Id, command: impl Fn() -> Arc<Command>) -> Job {
self.get_job(id)
.unwrap_or_else(|| self.create_job_with_id(id, command()))
}
#[must_use]
pub fn get_job(&self, id: Id) -> Option<Job> {
self.extant.get(&id).cloned()
}
pub fn list_jobs(&self) -> impl Iterator<Item = (Id, Job)> + '_ {
self.extant.iter().map(|(id, job)| (*id, job.clone()))
}
pub fn quit(&mut self) {
self.quit = Some(QuitManner::Abort);
}
pub fn quit_gracefully(&mut self, signal: Signal, grace: Duration) {
self.quit = Some(QuitManner::Graceful { signal, grace });
}
pub fn signals(&self) -> impl Iterator<Item = Signal> + '_ {
self.events.iter().flat_map(Event::signals)
}
pub fn paths(&self) -> impl Iterator<Item = (&Path, Option<&FileType>)> + '_ {
self.events.iter().flat_map(Event::paths)
}
pub fn completions(&self) -> impl Iterator<Item = Option<ProcessEnd>> + '_ {
self.events.iter().flat_map(Event::completions)
}
}