use std::{io, path::Path};
#[cfg(target_os = "linux")]
#[path = "path_watch/linux.rs"]
mod platform;
#[cfg(target_os = "macos")]
#[path = "path_watch/macos.rs"]
mod platform;
pub struct PathChangeWatch {
#[cfg(any(target_os = "linux", target_os = "macos"))]
watch: platform::Watch,
process: u32,
changed: bool,
}
impl PathChangeWatch {
pub fn new(path: &Path) -> io::Result<Self> {
#[cfg(any(target_os = "linux", target_os = "macos"))]
{
if path.components().any(|component| {
matches!(
component,
std::path::Component::CurDir | std::path::Component::ParentDir
)
}) {
return Err(unsupported());
}
let parent = path
.parent()
.filter(|_| path.is_absolute())
.ok_or_else(unsupported)?;
let watch = platform::Watch::new(parent)?;
if path.symlink_metadata()?.file_type().is_symlink() {
return Err(unsupported());
}
Ok(Self {
watch,
process: std::process::id(),
changed: false,
})
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
let _ = path;
Err(unsupported())
}
}
pub fn changed(&mut self) -> io::Result<bool> {
if self.changed || self.process != std::process::id() {
return Ok(true);
}
self.changed = true;
#[cfg(any(target_os = "linux", target_os = "macos"))]
{
self.changed = self.watch.changed()?;
}
Ok(self.changed)
}
}
fn unsupported() -> io::Error {
io::Error::new(
io::ErrorKind::Unsupported,
"pathname requires direct identity checks",
)
}
#[cfg(all(test, any(target_os = "linux", target_os = "macos")))]
mod tests;