feat(lib): make it possible to watch non-recursively

This commit is contained in:
Félix Saparelli 2024-04-27 22:10:16 +12:00
parent a4df258735
commit 0504c6c24f
No known key found for this signature in database
1 changed files with 53 additions and 12 deletions

View File

@ -76,35 +76,71 @@ impl Watcher {
///
/// This is currently only a wrapper around a [`PathBuf`], but may be augmented in the future.
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WatchedPath(PathBuf);
pub struct WatchedPath {
path: PathBuf,
recursive: bool,
}
impl From<PathBuf> for WatchedPath {
fn from(path: PathBuf) -> Self {
Self(path)
Self {
path,
recursive: true,
}
}
}
impl From<&str> for WatchedPath {
fn from(path: &str) -> Self {
Self(path.into())
Self {
path: path.into(),
recursive: true,
}
}
}
impl From<&Path> for WatchedPath {
fn from(path: &Path) -> Self {
Self(path.into())
Self {
path: path.into(),
recursive: true,
}
}
}
impl From<WatchedPath> for PathBuf {
fn from(path: WatchedPath) -> Self {
path.0
path.path
}
}
impl From<&WatchedPath> for PathBuf {
fn from(path: &WatchedPath) -> Self {
path.path.clone()
}
}
impl AsRef<Path> for WatchedPath {
fn as_ref(&self) -> &Path {
self.0.as_ref()
self.path.as_ref()
}
}
impl WatchedPath {
/// Create a new watched path, recursively descending into subdirectories.
pub fn recursive(path: impl Into<PathBuf>) -> Self {
Self {
path: path.into(),
recursive: true,
}
}
/// Create a new watched path, not descending into subdirectories.
pub fn non_recursive(path: impl Into<PathBuf>) -> Self {
Self {
path: path.into(),
recursive: false,
}
}
}
@ -222,7 +258,7 @@ pub async fn worker(
for path in to_drop {
trace!(?path, "removing path from the watcher");
if let Err(err) = watcher.unwatch(path.as_ref()) {
if let Err(err) = watcher.unwatch(path.path.as_ref()) {
error!(?err, "notify unwatch() error");
for e in notify_multi_path_errors(watcher_type, path, err, true) {
errors.send(e).await?;
@ -234,13 +270,18 @@ pub async fn worker(
for path in to_watch {
trace!(?path, "adding path to the watcher");
if let Err(err) = watcher.watch(path.as_ref(), notify::RecursiveMode::Recursive) {
if let Err(err) = watcher.watch(
path.path.as_ref(),
if path.recursive {
notify::RecursiveMode::Recursive
} else {
notify::RecursiveMode::NonRecursive
},
) {
error!(?err, "notify watch() error");
for e in notify_multi_path_errors(watcher_type, path, err, false) {
errors.send(e).await?;
}
// TODO: unwatch and re-watch manually while ignoring all the erroring paths
// See https://github.com/watchexec/watchexec/issues/218
} else {
pathset.insert(path);
}
@ -250,13 +291,13 @@ pub async fn worker(
fn notify_multi_path_errors(
kind: Watcher,
path: WatchedPath,
watched_path: WatchedPath,
mut err: notify::Error,
rm: bool,
) -> Vec<RuntimeError> {
let mut paths = take(&mut err.paths);
if paths.is_empty() {
paths.push(path.into());
paths.push(watched_path.into());
}
let generic = err.to_string();