watchexec/lib/src/event.rs

125 lines
3.1 KiB
Rust
Raw Normal View History

//! Synthetic event type, derived from inputs, triggers actions.
//!
2021-08-16 11:49:12 +02:00
//! Fundamentally, events in watchexec have three purposes:
//!
//! 1. To trigger the launch, restart, or other interruption of a process;
//! 2. To be filtered upon according to whatever set of criteria is desired;
//! 3. To carry information about what caused the event, which may be provided to the process.
2021-08-22 12:06:12 +02:00
use std::{
collections::HashMap,
2021-09-02 21:57:59 +02:00
fmt,
2021-08-22 12:06:12 +02:00
path::{Path, PathBuf},
process::ExitStatus,
2021-08-22 12:06:12 +02:00
};
2021-08-16 11:49:12 +02:00
2021-09-02 22:14:04 +02:00
use notify::EventKind;
2021-08-17 11:41:13 +02:00
use crate::signal::Signal;
2021-08-16 11:49:12 +02:00
/// An event, as far as watchexec cares about.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
2021-08-16 11:49:12 +02:00
pub struct Event {
2021-09-13 09:34:40 +02:00
pub tags: Vec<Tag>,
2021-08-16 11:49:12 +02:00
pub metadata: HashMap<String, Vec<String>>,
}
/// Something which can be used to filter or qualify an event.
2021-08-16 11:49:12 +02:00
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
2021-09-13 09:34:40 +02:00
pub enum Tag {
2021-08-16 11:49:12 +02:00
Path(PathBuf),
2021-09-02 22:14:04 +02:00
FileEventKind(EventKind),
2021-08-16 11:49:12 +02:00
Source(Source),
Process(u32),
2021-08-17 11:41:13 +02:00
Signal(Signal),
ProcessCompletion(Option<ExitStatus>),
2021-08-16 11:49:12 +02:00
}
impl Tag {
pub const fn discriminant_name(&self) -> &'static str {
match self {
Tag::Path(_) => "Path",
Tag::FileEventKind(_) => "FileEventKind",
Tag::Source(_) => "Source",
Tag::Process(_) => "Process",
Tag::Signal(_) => "Signal",
Tag::ProcessCompletion(_) => "ProcessCompletion",
}
}
}
2021-08-16 11:49:12 +02:00
/// The general origin of the event.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Source {
Filesystem,
Keyboard,
Mouse,
2021-08-17 11:41:13 +02:00
Os,
2021-08-16 11:49:12 +02:00
Time,
2021-09-02 21:57:45 +02:00
Internal,
2021-08-16 11:49:12 +02:00
}
2021-08-22 12:06:12 +02:00
impl fmt::Display for Source {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", match self {
Self::Filesystem => "filesystem",
Self::Keyboard => "keyboard",
Self::Mouse => "mouse",
Self::Os => "os",
Self::Time => "time",
Self::Internal => "internal",
})
}
}
2021-08-22 12:06:12 +02:00
impl Event {
2021-09-13 09:34:40 +02:00
/// Return all paths in the event's tags.
2021-08-22 12:06:12 +02:00
pub fn paths(&self) -> impl Iterator<Item = &Path> {
2021-09-13 09:34:40 +02:00
self.tags.iter().filter_map(|p| match p {
Tag::Path(p) => Some(p.as_path()),
2021-08-22 12:06:12 +02:00
_ => None,
})
}
2021-09-02 23:25:06 +02:00
2021-09-13 09:34:40 +02:00
/// Return all signals in the event's tags.
pub fn signals(&self) -> impl Iterator<Item = Signal> + '_ {
2021-09-13 09:34:40 +02:00
self.tags.iter().filter_map(|p| match p {
Tag::Signal(s) => Some(*s),
_ => None,
})
}
2021-09-02 23:25:06 +02:00
2021-09-13 09:34:40 +02:00
/// Return all process completions in the event's tags.
2021-09-02 23:25:06 +02:00
pub fn completions(&self) -> impl Iterator<Item = Option<ExitStatus>> + '_ {
2021-09-13 09:34:40 +02:00
self.tags.iter().filter_map(|p| match p {
Tag::ProcessCompletion(s) => Some(*s),
2021-09-02 23:25:06 +02:00
_ => None,
})
}
2021-08-22 12:06:12 +02:00
}
2021-09-02 21:57:59 +02:00
impl fmt::Display for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Event")?;
2021-09-13 09:34:40 +02:00
for p in &self.tags {
2021-09-02 21:57:59 +02:00
match p {
2021-09-13 09:34:40 +02:00
Tag::Path(p) => write!(f, " path={}", p.display())?,
Tag::FileEventKind(kind) => write!(f, " kind={:?}", kind)?,
Tag::Source(s) => write!(f, " source={:?}", s)?,
Tag::Process(p) => write!(f, " process={}", p)?,
Tag::Signal(s) => write!(f, " signal={:?}", s)?,
Tag::ProcessCompletion(None) => write!(f, " command-completed")?,
Tag::ProcessCompletion(Some(c)) => write!(f, " command-completed({})", c)?,
2021-09-02 21:57:59 +02:00
}
}
if !self.metadata.is_empty() {
write!(f, " meta: {:?}", self.metadata)?;
}
Ok(())
}
}