use crate::Watcher; use anyhow::{Context as _, Result}; use collections::{BTreeMap, Bound}; use fsevent::EventStream; use parking_lot::Mutex; use std::{ path::{Path, PathBuf}, sync::Weak, time::Duration, }; pub struct MacWatcher { events_tx: smol::channel::Sender>, handles: Weak>>, latency: Duration, } impl MacWatcher { pub fn new( events_tx: smol::channel::Sender>, handles: Weak>>, latency: Duration, ) -> Self { Self { events_tx, handles, latency, } } } impl Watcher for MacWatcher { fn add(&self, path: &Path) -> Result<()> { let handles = self .handles .upgrade() .context("unable to watch path, receiver dropped")?; let mut handles = handles.lock(); // Return early if an ancestor of this path was already being watched. if let Some((watched_path, _)) = handles .range::((Bound::Unbounded, Bound::Included(path))) .next_back() { if path.starts_with(watched_path) { return Ok(()); } } let (stream, handle) = EventStream::new(&[path], self.latency); let tx = self.events_tx.clone(); std::thread::spawn(move || { stream.run(move |events| smol::block_on(tx.send(events)).is_ok()); }); handles.insert(path.into(), handle); Ok(()) } fn remove(&self, path: &Path) -> gpui::Result<()> { let handles = self .handles .upgrade() .context("unable to remove path, receiver dropped")?; let mut handles = handles.lock(); handles.remove(path); Ok(()) } }