Replace std FileType with our own (serde-able) enum

This commit is contained in:
Félix Saparelli 2021-10-20 01:18:43 +13:00
parent 401437784d
commit 6671863f2f
No known key found for this signature in database
GPG Key ID: B948C4BAE44FC474
4 changed files with 57 additions and 30 deletions

View File

@ -9,7 +9,6 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
fmt, fmt,
fs::FileType,
path::{Path, PathBuf}, path::{Path, PathBuf},
process::ExitStatus, process::ExitStatus,
}; };
@ -54,6 +53,7 @@ pub enum Tag {
Signal(MainSignal), Signal(MainSignal),
/// The event is about the subprocess exiting. /// The event is about the subprocess exiting.
// TODO: replace ExitStatus with something we can de/serialize.
ProcessCompletion(Option<ExitStatus>), ProcessCompletion(Option<ExitStatus>),
} }
@ -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<std::fs::FileType> 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. /// The general origin of the event.
/// ///
/// This is set by the event source. Note that not all of these are currently used. /// 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 } => { Tag::Path { path, file_type } => {
write!(f, " path={}", path.display())?; write!(f, " path={}", path.display())?;
if let Some(ft) = file_type { if let Some(ft) = file_type {
write!( write!(f, " filetype={}", ft)?;
f,
" filetype={}",
if ft.is_file() {
"file"
} else if ft.is_dir() {
"dir"
} else if ft.is_symlink() {
"symlink"
} else {
"special"
}
)?;
} }
} }
Tag::FileEventKind(kind) => write!(f, " kind={:?}", kind)?, Tag::FileEventKind(kind) => write!(f, " kind={:?}", kind)?,

View File

@ -8,7 +8,7 @@ use tokio::fs::read_to_string;
use tracing::{debug, trace}; use tracing::{debug, trace};
use crate::error::RuntimeError; use crate::error::RuntimeError;
use crate::event::Event; use crate::event::{Event, FileType};
use crate::filter::Filterer; use crate::filter::Filterer;
use crate::ignore_files::IgnoreFile; use crate::ignore_files::IgnoreFile;
@ -98,7 +98,9 @@ impl Filterer for GlobsetFilterer {
/// This implementation never errors. /// This implementation never errors.
fn check_event(&self, event: &Event) -> Result<bool, RuntimeError> { fn check_event(&self, event: &Event) -> Result<bool, RuntimeError> {
for (path, file_type) in event.paths() { 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() { if self.ignores.matched(path, is_dir).is_ignore() {
trace!(?path, "ignored by globset ignore"); trace!(?path, "ignored by globset ignore");

View File

@ -13,7 +13,7 @@ use tracing::{debug, trace, warn};
use unicase::UniCase; use unicase::UniCase;
use crate::error::RuntimeError; use crate::error::RuntimeError;
use crate::event::{Event, Tag}; use crate::event::{Event, FileType, Tag};
use crate::filter::tagged::error::TaggedFiltererError; use crate::filter::tagged::error::TaggedFiltererError;
use crate::filter::Filterer; use crate::filter::Filterer;
use crate::ignore_files::IgnoreFile; use crate::ignore_files::IgnoreFile;
@ -131,7 +131,7 @@ impl TaggedFilterer {
let mut tag_match = true; let mut tag_match = true;
if let (Matcher::Path, Tag::Path { path, file_type }) = (matcher, tag) { 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(); let gc = self.glob_compiled.borrow();
if let Some(igs) = gc.as_ref() { if let Some(igs) = gc.as_ref() {
@ -311,15 +311,7 @@ impl TaggedFilterer {
.. ..
}, },
Matcher::FileType, Matcher::FileType,
) => filter.matches(if ft.is_dir() { ) => filter.matches(ft.to_string()),
"dir"
} else if ft.is_file() {
"file"
} else if ft.is_symlink() {
"symlink"
} else {
"special"
}),
(Tag::FileEventKind(kind), Matcher::FileEventKind) => { (Tag::FileEventKind(kind), Matcher::FileEventKind) => {
filter.matches(format!("{:?}", kind)) filter.matches(format!("{:?}", kind))
} }
@ -588,8 +580,8 @@ pub enum Matcher {
/// ///
/// This is not guaranteed to be present for every filesystem event. /// 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 /// It can be any of these values: `file`, `dir`, `symlink`, `other`. That last one means
/// "not any of the first three," it does not mean "a special file" as defined by the OS. /// "not any of the first three."
FileType, FileType,
/// The [`EventKind`][notify::event::EventKind] of a filesystem event. /// The [`EventKind`][notify::event::EventKind] of a filesystem event.

View File

@ -285,7 +285,7 @@ fn process_event(
for path in nev.paths { for path in nev.paths {
// possibly pull file_type from whatever notify (or the native driver) returns? // possibly pull file_type from whatever notify (or the native driver) returns?
tags.push(Tag::Path { 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)?, path: dunce::canonicalize(path)?,
}); });
} }