diff options
Diffstat (limited to 'cli/ops')
-rw-r--r-- | cli/ops/fs_events.rs | 129 | ||||
-rw-r--r-- | cli/ops/mod.rs | 1 |
2 files changed, 130 insertions, 0 deletions
diff --git a/cli/ops/fs_events.rs b/cli/ops/fs_events.rs new file mode 100644 index 000000000..471556b5a --- /dev/null +++ b/cli/ops/fs_events.rs @@ -0,0 +1,129 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +use super::dispatch_json::{Deserialize, JsonOp, Value}; +use crate::deno_error::bad_resource; +use crate::ops::json_op; +use crate::state::State; +use deno_core::*; +use futures::future::poll_fn; +use futures::future::FutureExt; +use notify::event::Event as NotifyEvent; +use notify::Error as NotifyError; +use notify::EventKind; +use notify::RecommendedWatcher; +use notify::RecursiveMode; +use notify::Watcher; +use serde::Serialize; +use std::convert::From; +use std::path::PathBuf; +use tokio::sync::mpsc; + +pub fn init(i: &mut Isolate, s: &State) { + i.register_op( + "fs_events_open", + s.core_op(json_op(s.stateful_op(op_fs_events_open))), + ); + i.register_op( + "fs_events_poll", + s.core_op(json_op(s.stateful_op(op_fs_events_poll))), + ); +} + +struct FsEventsResource { + #[allow(unused)] + watcher: RecommendedWatcher, + receiver: mpsc::Receiver<Result<FsEvent, ErrBox>>, +} + +/// Represents a file system event. +/// +/// We do not use the event directly from the notify crate. We flatten +/// the structure into this simpler structure. We want to only make it more +/// complex as needed. +/// +/// Feel free to expand this struct as long as you can add tests to demonstrate +/// the complexity. +#[derive(Serialize, Debug)] +struct FsEvent { + kind: String, + paths: Vec<PathBuf>, +} + +impl From<NotifyEvent> for FsEvent { + fn from(e: NotifyEvent) -> Self { + let kind = match e.kind { + EventKind::Any => "any", + EventKind::Access(_) => "access", + EventKind::Create(_) => "create", + EventKind::Modify(_) => "modify", + EventKind::Remove(_) => "remove", + EventKind::Other => todo!(), // What's this for? Leaving it out for now. + } + .to_string(); + FsEvent { + kind, + paths: e.paths, + } + } +} + +pub fn op_fs_events_open( + state: &State, + args: Value, + _zero_copy: Option<ZeroCopyBuf>, +) -> Result<JsonOp, ErrBox> { + #[derive(Deserialize)] + struct OpenArgs { + recursive: bool, + paths: Vec<String>, + } + let args: OpenArgs = serde_json::from_value(args)?; + let (sender, receiver) = mpsc::channel::<Result<FsEvent, ErrBox>>(16); + let sender = std::sync::Mutex::new(sender); + let mut watcher: RecommendedWatcher = + Watcher::new_immediate(move |res: Result<NotifyEvent, NotifyError>| { + let res2 = res.map(FsEvent::from).map_err(ErrBox::from); + let mut sender = sender.lock().unwrap(); + futures::executor::block_on(sender.send(res2)).expect("fs events error"); + })?; + let recursive_mode = if args.recursive { + RecursiveMode::Recursive + } else { + RecursiveMode::NonRecursive + }; + for path in &args.paths { + state.check_read(&PathBuf::from(path))?; + watcher.watch(path, recursive_mode)?; + } + let resource = FsEventsResource { watcher, receiver }; + let table = &mut state.borrow_mut().resource_table; + let rid = table.add("fsEvents", Box::new(resource)); + Ok(JsonOp::Sync(json!(rid))) +} + +pub fn op_fs_events_poll( + state: &State, + args: Value, + _zero_copy: Option<ZeroCopyBuf>, +) -> Result<JsonOp, ErrBox> { + #[derive(Deserialize)] + struct PollArgs { + rid: u32, + } + let PollArgs { rid } = serde_json::from_value(args)?; + let state = state.clone(); + let f = poll_fn(move |cx| { + let resource_table = &mut state.borrow_mut().resource_table; + let watcher = resource_table + .get_mut::<FsEventsResource>(rid) + .ok_or_else(bad_resource)?; + watcher + .receiver + .poll_recv(cx) + .map(|maybe_result| match maybe_result { + Some(Ok(value)) => Ok(json!({ "value": value, "done": false })), + Some(Err(err)) => Err(err), + None => Ok(json!({ "done": true })), + }) + }); + Ok(JsonOp::Async(f.boxed_local())) +} diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs index dd772cd9a..7746143db 100644 --- a/cli/ops/mod.rs +++ b/cli/ops/mod.rs @@ -13,6 +13,7 @@ pub mod errors; pub mod fetch; pub mod files; pub mod fs; +pub mod fs_events; pub mod io; pub mod net; pub mod os; |