summaryrefslogtreecommitdiff
path: root/cli/ops
diff options
context:
space:
mode:
Diffstat (limited to 'cli/ops')
-rw-r--r--cli/ops/fs_events.rs129
-rw-r--r--cli/ops/mod.rs1
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;