diff --git a/lib/src/event.rs b/lib/src/event.rs index 96492d8..9f628de 100644 --- a/lib/src/event.rs +++ b/lib/src/event.rs @@ -9,7 +9,6 @@ use std::{ collections::HashMap, fmt, - fs::FileType, path::{Path, PathBuf}, process::ExitStatus, }; @@ -54,6 +53,7 @@ pub enum Tag { Signal(MainSignal), /// The event is about the subprocess exiting. + // TODO: replace ExitStatus with something we can de/serialize. ProcessCompletion(Option), } @@ -71,6 +71,51 @@ impl Tag { } } +/// The type of a file. +/// +/// This is a simplification of the [`std::fs::FileType`] type, which is not constructable and may +/// differ on different platforms. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum FileType { + /// A regular file. + File, + + /// A directory. + Dir, + + /// A symbolic link. + Symlink, + + /// Something else. + Other, +} + +impl From for FileType { + fn from(ft: std::fs::FileType) -> Self { + if ft.is_file() { + Self::File + } else if ft.is_dir() { + Self::Dir + } else if ft.is_symlink() { + Self::Symlink + } else { + Self::Other + } + } +} + +impl fmt::Display for FileType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::File => write!(f, "file"), + Self::Dir => write!(f, "dir"), + Self::Symlink => write!(f, "symlink"), + Self::Other => write!(f, "other"), + } + } +} + /// The general origin of the event. /// /// This is set by the event source. Note that not all of these are currently used. @@ -159,19 +204,7 @@ impl fmt::Display for Event { Tag::Path { path, file_type } => { write!(f, " path={}", path.display())?; if let Some(ft) = file_type { - write!( - f, - " filetype={}", - if ft.is_file() { - "file" - } else if ft.is_dir() { - "dir" - } else if ft.is_symlink() { - "symlink" - } else { - "special" - } - )?; + write!(f, " filetype={}", ft)?; } } Tag::FileEventKind(kind) => write!(f, " kind={:?}", kind)?, diff --git a/lib/src/filter/globset.rs b/lib/src/filter/globset.rs index 773c365..43e86af 100644 --- a/lib/src/filter/globset.rs +++ b/lib/src/filter/globset.rs @@ -8,7 +8,7 @@ use tokio::fs::read_to_string; use tracing::{debug, trace}; use crate::error::RuntimeError; -use crate::event::Event; +use crate::event::{Event, FileType}; use crate::filter::Filterer; use crate::ignore_files::IgnoreFile; @@ -98,7 +98,9 @@ impl Filterer for GlobsetFilterer { /// This implementation never errors. fn check_event(&self, event: &Event) -> Result { for (path, file_type) in event.paths() { - let is_dir = file_type.map(|t| t.is_dir()).unwrap_or(false); + let is_dir = file_type + .map(|t| matches!(t, FileType::Dir)) + .unwrap_or(false); if self.ignores.matched(path, is_dir).is_ignore() { trace!(?path, "ignored by globset ignore"); diff --git a/lib/src/filter/tagged.rs b/lib/src/filter/tagged.rs index f1fc785..a83b98d 100644 --- a/lib/src/filter/tagged.rs +++ b/lib/src/filter/tagged.rs @@ -13,7 +13,7 @@ use tracing::{debug, trace, warn}; use unicase::UniCase; use crate::error::RuntimeError; -use crate::event::{Event, Tag}; +use crate::event::{Event, FileType, Tag}; use crate::filter::tagged::error::TaggedFiltererError; use crate::filter::Filterer; use crate::ignore_files::IgnoreFile; @@ -131,7 +131,7 @@ impl TaggedFilterer { let mut tag_match = true; if let (Matcher::Path, Tag::Path { path, file_type }) = (matcher, tag) { - let is_dir = file_type.map_or(false, |ft| ft.is_dir()); + let is_dir = file_type.map_or(false, |ft| matches!(ft, FileType::Dir)); let gc = self.glob_compiled.borrow(); if let Some(igs) = gc.as_ref() { @@ -311,15 +311,7 @@ impl TaggedFilterer { .. }, Matcher::FileType, - ) => filter.matches(if ft.is_dir() { - "dir" - } else if ft.is_file() { - "file" - } else if ft.is_symlink() { - "symlink" - } else { - "special" - }), + ) => filter.matches(ft.to_string()), (Tag::FileEventKind(kind), Matcher::FileEventKind) => { filter.matches(format!("{:?}", kind)) } @@ -588,8 +580,8 @@ pub enum Matcher { /// /// This is not guaranteed to be present for every filesystem event. /// - /// It can be any of these values: `file`, `dir`, `symlink`, `special`. That last one means - /// "not any of the first three," it does not mean "a special file" as defined by the OS. + /// It can be any of these values: `file`, `dir`, `symlink`, `other`. That last one means + /// "not any of the first three." FileType, /// The [`EventKind`][notify::event::EventKind] of a filesystem event. diff --git a/lib/src/fs.rs b/lib/src/fs.rs index 40f2843..9506cb7 100644 --- a/lib/src/fs.rs +++ b/lib/src/fs.rs @@ -285,7 +285,7 @@ fn process_event( for path in nev.paths { // possibly pull file_type from whatever notify (or the native driver) returns? tags.push(Tag::Path { - file_type: metadata(&path).ok().map(|m| m.file_type()), + file_type: metadata(&path).ok().map(|m| m.file_type().into()), path: dunce::canonicalize(path)?, }); }