From ea220f36a89e9ab8cf68a29348fbc728be31ea89 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 10 May 2020 13:40:03 +0200 Subject: [PATCH] Move filewatcher to own repo (#423) --- doc/pods.md | 7 +- .../pods/pod-babashka-filewatcher/.gitignore | 1 - .../pods/pod-babashka-filewatcher/Cargo.lock | 292 ---------------- .../pods/pod-babashka-filewatcher/Cargo.toml | 12 - .../pods/pod-babashka-filewatcher/README.md | 18 - .../pod-babashka-filewatcher/src/bencode.rs | 320 ------------------ .../pods/pod-babashka-filewatcher/src/main.rs | 137 -------- 7 files changed, 3 insertions(+), 784 deletions(-) delete mode 100644 examples/pods/pod-babashka-filewatcher/.gitignore delete mode 100644 examples/pods/pod-babashka-filewatcher/Cargo.lock delete mode 100644 examples/pods/pod-babashka-filewatcher/Cargo.toml delete mode 100644 examples/pods/pod-babashka-filewatcher/README.md delete mode 100644 examples/pods/pod-babashka-filewatcher/src/bencode.rs delete mode 100644 examples/pods/pod-babashka-filewatcher/src/main.rs diff --git a/doc/pods.md b/doc/pods.md index 993507cc..2351b02f 100644 --- a/doc/pods.md +++ b/doc/pods.md @@ -19,7 +19,9 @@ Currently the following pods are available: - [clj-kondo](https://github.com/borkdude/clj-kondo/#babashka-pod): a Clojure linter -- [pod-babashka-hsqldb](https://github.com/borkdude/pod-babashka-hsqldb): a pod +- [pod-babashka-filewatcher](https://github.com/babashka/pod-babashka-hsqldb): a + filewatcher pod based on Rust notify. +- [pod-babashka-hsqldb](https://github.com/babashka/pod-babashka-hsqldb): a pod that allows you to create and fire queries at a [HSQLDB](http://www.hsqldb.org/) database. @@ -39,9 +41,6 @@ can be found [here](../examples/pods): allows you to create and fire queries at a [sqlite](https://www.sqlite.org/) database. Implemented in Python. -- [pod-babashka-filewatcher](../examples/pods/pod-babashka-filewatcher): a - filewatcher pod. Implemented in Rust. - ### Naming When choosing a name for your pod, we suggest the following naming scheme: diff --git a/examples/pods/pod-babashka-filewatcher/.gitignore b/examples/pods/pod-babashka-filewatcher/.gitignore deleted file mode 100644 index ea8c4bf7..00000000 --- a/examples/pods/pod-babashka-filewatcher/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/examples/pods/pod-babashka-filewatcher/Cargo.lock b/examples/pods/pod-babashka-filewatcher/Cargo.lock deleted file mode 100644 index 4798333a..00000000 --- a/examples/pods/pod-babashka-filewatcher/Cargo.lock +++ /dev/null @@ -1,292 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "filetime" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi 0.3.8", -] - -[[package]] -name = "fsevent" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" -dependencies = [ - "bitflags", - "fsevent-sys", -] - -[[package]] -name = "fsevent-sys" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" -dependencies = [ - "libc", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "inotify" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -dependencies = [ - "libc", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "json" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "lazycell" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" - -[[package]] -name = "libc" -version = "0.2.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" - -[[package]] -name = "log" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "mio" -version = "0.6.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" -dependencies = [ - "cfg-if", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "net2" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" -dependencies = [ - "cfg-if", - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "notify" -version = "4.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" -dependencies = [ - "bitflags", - "filetime", - "fsevent", - "fsevent-sys", - "inotify", - "libc", - "mio", - "mio-extras", - "walkdir", - "winapi 0.3.8", -] - -[[package]] -name = "pod-babashka-filewatcher" -version = "0.1.0" -dependencies = [ - "json", - "log", - "notify", -] - -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" - -[[package]] -name = "walkdir" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -dependencies = [ - "same-file", - "winapi 0.3.8", - "winapi-util", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.8", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] diff --git a/examples/pods/pod-babashka-filewatcher/Cargo.toml b/examples/pods/pod-babashka-filewatcher/Cargo.toml deleted file mode 100644 index ee787dac..00000000 --- a/examples/pods/pod-babashka-filewatcher/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "pod-babashka-filewatcher" -version = "0.1.0" -authors = ["Michiel Borkent "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -notify = "4.0.12" -json = "0.12.4" -log = "0.4" diff --git a/examples/pods/pod-babashka-filewatcher/README.md b/examples/pods/pod-babashka-filewatcher/README.md deleted file mode 100644 index b32bc929..00000000 --- a/examples/pods/pod-babashka-filewatcher/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# pod-babashka-filewatcher - -## Compile - -``` -$ cargo build --release -``` - -## Run - -``` clojure -(babashka.pods/load-pod "target/release/pod-babashka-filewatcher") -(def chan (pod.babashka.filewatcher/watch "/tmp")) -(require '[clojure.core.async :as async]) -(loop [] (prn (async/ ["changed" "/tmp"] -;;=> ["changed" "/tmp"] -``` diff --git a/examples/pods/pod-babashka-filewatcher/src/bencode.rs b/examples/pods/pod-babashka-filewatcher/src/bencode.rs deleted file mode 100644 index aea08fef..00000000 --- a/examples/pods/pod-babashka-filewatcher/src/bencode.rs +++ /dev/null @@ -1,320 +0,0 @@ -// from https://github.com/jasilven/redbush/blob/master/src/nrepl/bencode.rs - -use std::collections::HashMap; -use std::convert::TryInto; -use std::fmt::{self, Display}; -use std::hash::Hash; -use std::hash::Hasher; -use std::io::BufRead; -use std::iter::Iterator; -use std::str::FromStr; -use std::string::ToString; - -type Result = std::result::Result; - -#[derive(Debug)] -pub enum BencodeError { - Error(String), - Io(std::io::Error), - Eof(), - Parse(std::num::ParseIntError), -} - -impl Display for BencodeError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - BencodeError::Error(s) => write!(f, "Bencode Error: {} ", s), - BencodeError::Io(e) => write!(f, "Bencode Io: {}", e), - BencodeError::Parse(e) => write!(f, "Bencode Parse: {}", e), - BencodeError::Eof() => write!(f, "Bencode Eof"), - } - } -} - -impl From for BencodeError { - fn from(err: std::io::Error) -> BencodeError { - BencodeError::Io(err) - } -} - -impl From for BencodeError { - fn from(err: std::num::ParseIntError) -> BencodeError { - BencodeError::Parse(err) - } -} - -#[derive(Clone, Debug, Eq)] -pub struct HMap(pub HashMap); - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum Value { - Map(HMap), - List(Vec), - Str(String), - Int(i32), -} - -impl From<&str> for Value { - fn from(s: &str) -> Self { - Value::Str(s.to_string()) - } -} - -impl From> for Value { - fn from(m: HashMap) -> Self { - Value::Map(HMap::new(m)) - } -} - -impl From> for Value { - fn from(map: HashMap<&str, &str>) -> Self { - let mut m = HashMap::new(); - for (k, v) in map { - m.insert(Value::Str(k.to_string()), Value::Str(v.to_string())); - } - let hm = HMap::new(m); - Value::Map(hm) - } -} - -impl TryInto> for Value { - type Error = BencodeError; - - fn try_into(self) -> std::result::Result, Self::Error> { - match self { - Value::Map(hm) => { - let mut map = HashMap::::new(); - for key in hm.0.keys() { - // safe to unwrap here - map.insert(format!("{}", &key), format!("{}", &hm.get(key).unwrap())); - } - Ok(map) - } - _ => Err(BencodeError::Error("Expected HashMap Value".into())), - } - } -} - -impl HMap { - pub fn new(map: HashMap) -> Self { - HMap(map) - } - - pub fn get(&self, key: &Value) -> Option<&Value> { - self.0.get(key) - } -} - -impl Hash for HMap { - fn hash(&self, state: &mut H) { - let mut keys: Vec = self.0.keys().map(|k| format!("{:?}", k)).collect(); - let mut vals: Vec = self.0.values().map(|v| format!("{:?}", v)).collect(); - keys.sort(); - vals.sort(); - keys.hash(state); - vals.hash(state); - } -} - -impl PartialEq for HMap { - fn eq(&self, other: &HMap) -> bool { - self.0.eq(&other.0) - } -} - -impl Display for Value { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Value::Map(hm) => { - let mut result = String::from("{"); - for (key, val) in hm.0.iter() { - result.push_str(&format!("{} {} ", &key, &val)); - } - let mut result = result.trim_end().to_string(); - result.push('}'); - write!(f, "{}", result) - } - Value::List(v) => { - let mut result = String::from("["); - for item in v { - result.push_str(&item.to_string()); - result.push_str(", "); - } - let mut result = result - .trim_end_matches(|c| c == ',' || c == ' ') - .to_string(); - result.push(']'); - write!(f, "{}", result) - } - Value::Str(s) => write!(f, "{}", s), - Value::Int(i) => write!(f, "{}", i), - } - } -} - -impl Value { - pub fn to_bencode(&self) -> String { - match self { - Value::Map(hm) => { - let mut result = String::from("d"); - for (key, val) in hm.0.iter() { - result.push_str(&format!("{}{}", key.to_bencode(), val.to_bencode())); - } - result.push('e'); - result - } - Value::List(v) => { - let mut result = String::from("l"); - for item in v { - result.push_str(&item.to_bencode()); - } - result.push('e'); - result - } - Value::Str(s) => format!("{}:{}", s.len(), s), - Value::Int(i) => format!("i{}e", i), - } - } -} - -pub fn parse_bencode(reader: &mut dyn BufRead) -> Result> { - log::debug!("Parsing bencode from reader"); - - let mut buf = vec![]; - buf.resize(1, 0); - match reader.read_exact(&mut buf[0..1]) { - Ok(()) => match buf[0] { - b'i' => match reader.read_until(b'e', &mut buf) { - Ok(cnt) => { - let s = String::from_utf8_lossy(&buf[1..cnt]); - let n = i32::from_str(&s)?; - Ok(Some(Value::Int(n))) - } - Err(e) => Err(e.into()), - }, - b'd' => { - let mut map = HashMap::new(); - loop { - match parse_bencode(reader) { - Ok(None) => return Ok(Some(Value::Map(HMap(map)))), - Ok(Some(v)) => map.insert(v, parse_bencode(reader)?.unwrap()), - Err(e) => return Err(e), - }; - } - } - b'l' => { - let mut list = Vec::::new(); - loop { - match parse_bencode(reader) { - Ok(None) => return Ok(Some(Value::List(list))), - Ok(Some(v)) => list.push(v), - Err(e) => return Err(e), - } - } - } - b'e' => Ok(None), - b'0' => { - reader.read_until(b':', &mut buf)?; - Ok(Some(Value::Str("".to_string()))) - } - _ => match reader.read_until(b':', &mut buf) { - Ok(_) => { - buf.resize(buf.len() - 1, 0); - let mut s = String::from(""); - buf.iter().for_each(|i| s.push(*i as char)); - let cnt = usize::from_str(&s)?; - buf.resize(cnt, 0); - reader.read_exact(&mut buf[0..cnt])?; - Ok(Some(Value::Str( - String::from_utf8_lossy(&buf[..]).to_string(), - ))) - } - Err(e) => Err(BencodeError::Io(e)), - }, - }, - Err(e) => match e.kind() { - std::io::ErrorKind::UnexpectedEof => (Err(BencodeError::Eof())), - _ => Err(BencodeError::Io(e)), - }, - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::io::BufReader; - - #[test] - fn test_parse_bencode_num() { - let left = vec![ - Value::Int(1), - Value::Int(10), - Value::Int(100_000), - Value::Int(-1), - Value::Int(-999), - ]; - let right = vec!["i1e", "i10e", "i100000e", "i-1e", "i-999e"]; - - for i in 0..left.len() { - let mut bufread = BufReader::new(right[i].as_bytes()); - assert_eq!(left[i], parse_bencode(&mut bufread).unwrap().unwrap()); - assert_eq!(left[i].to_bencode(), right[i]); - } - } - - #[test] - fn test_parse_bencode_str() { - let left = vec![ - Value::Str("foo".to_string()), - Value::Str("1234567890\n".to_string()), - Value::Str("".to_string()), - ]; - let right = vec!["3:foo", "11:1234567890\n", "0:"]; - for i in 0..left.len() { - let mut bufread = BufReader::new(right[i].as_bytes()); - assert_eq!(left[i], parse_bencode(&mut bufread).unwrap().unwrap()); - assert_eq!(left[i].to_bencode(), right[i]); - } - } - - #[test] - fn test_parse_bencode_list() { - let left = vec![ - (Value::List(vec![Value::Int(1), Value::Int(2), Value::Int(3)])), - (Value::List(vec![ - Value::Int(1), - Value::Str("foo".to_string()), - Value::Int(3), - ])), - (Value::List(vec![Value::Str("".to_string())])), - ]; - let right = vec!["li1ei2ei3ee", "li1e3:fooi3ee", "l0:e"]; - for i in 0..left.len() { - let mut bufread = BufReader::new(right[i].as_bytes()); - assert_eq!(left[i], parse_bencode(&mut bufread).unwrap().unwrap()); - assert_eq!(left[i].to_bencode(), right[i]); - } - } - - #[test] - fn test_parse_bencode_map() { - let mut m1 = HashMap::new(); - m1.insert(Value::Str("bar".to_string()), Value::Str("baz".to_string())); - let m1_c = m1.clone(); - let left1 = Value::Map(HMap::new(m1)); - - let mut m2 = HashMap::new(); - m2.insert(Value::Str("foo".to_string()), Value::Map(HMap::new(m1_c))); - let left2 = Value::Map(HMap::new(m2)); - - let sright1 = "d3:bar3:baze".to_string(); - let mut right1 = BufReader::new(sright1.as_bytes()); - assert_eq!(left1, parse_bencode(&mut right1).unwrap().unwrap()); - assert_eq!(left1.to_bencode(), sright1); - - let sright2 = "d3:food3:bar3:bazee".to_string(); - let mut right2 = BufReader::new(sright2.as_bytes()); - assert_eq!(left2, parse_bencode(&mut right2).unwrap().unwrap()); - assert_eq!(left2.to_bencode(), sright2); - } -} diff --git a/examples/pods/pod-babashka-filewatcher/src/main.rs b/examples/pods/pod-babashka-filewatcher/src/main.rs deleted file mode 100644 index 74b0bd70..00000000 --- a/examples/pods/pod-babashka-filewatcher/src/main.rs +++ /dev/null @@ -1,137 +0,0 @@ -// see https://github.com/jasilven/redbush/blob/master/src/nrepl/mod.rs - -mod bencode; -use bencode::{Value}; -use bencode as bc; - -use notify::{Watcher, RecursiveMode, watcher}; -use std::sync::mpsc::channel; -use std::time::Duration; - -use std::collections::HashMap; -use std::io; -use std::io::{Write, BufReader}; - -use json; - -fn get_string(val: &bc::Value, key: &str) -> Option { - match val { - bc::Value::Map(hm) => { - match hm.get(&Value::from(key)) { - Some(Value::Str(s)) => - Some(String::from(s)), - _ => None - } - }, - _ => None - } -} - -fn insert(mut m: HashMap, k: &str, v: &str) -> HashMap { - m.insert(Value::from(k), Value::from(v)); - m -} - -fn describe() { - let namespace = HashMap::new(); - let mut namespace = insert(namespace, "name", "pod.babashka.filewatcher"); - let mut vars = Vec::new(); - let var_map = HashMap::new(); - let var_map = insert(var_map, "name", "watch"); - let var_map = insert(var_map, "async", "true"); - vars.push(Value::from(var_map)); - namespace.insert(Value::from("vars"),Value::List(vars)); - let describe_map = HashMap::new(); - let mut describe_map = insert(describe_map, "format", "json"); - let namespaces = vec![Value::from(namespace)]; - let namespaces = Value::List(namespaces); - describe_map.insert(Value::from("namespaces"), namespaces); - let describe_map = Value::from(describe_map); - let bencode = describe_map.to_bencode(); - let stdout = io::stdout(); - let mut handle = stdout.lock(); - handle.write_all(bencode.as_bytes()).unwrap(); - handle.flush().unwrap(); -} - -fn path_changed(id: &str, path: &str) { - let reply = HashMap::new(); - let reply = insert(reply, "id", id); - let value = vec!["changed", path]; - let value = json::stringify(value); - let mut reply = insert(reply, "value", &value); - let status = vec![Value::from("status")]; - reply.insert(Value::from("status"),Value::List(status)); - let bencode = Value::from(reply).to_bencode(); - let stdout = io::stdout(); - let mut handle = stdout.lock(); - handle.write_all(bencode.as_bytes()).unwrap(); - handle.flush().unwrap(); -} - -fn watch(id: &str, path: &str) { - let (tx, rx) = channel(); - let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap(); - watcher.watch(path, RecursiveMode::Recursive).unwrap(); - loop { - match rx.recv() { - Ok(_) => { - path_changed(id, path); - }, - Err(e) => panic!("watch error: {:?}", e), - } - } - -} - -fn handle_incoming(val: bc::Value) { - let op = get_string(&val, "op").unwrap(); - match &op[..] { - "describe" => { - describe() - - }, - "invoke" => { - let var = get_string(&val, "var").unwrap(); - match &var[..] { - "pod.babashka.filewatcher/watch" => { - let args = get_string(&val, "args").unwrap(); - let args = json::parse(&args).unwrap(); - let path = &args[0]; - let path = path.as_str().unwrap(); - let id = get_string(&val, "id").unwrap(); - watch(&id, path); - }, - _ => panic!(var) - }; - }, - _ => panic!(op) - } -} - - -fn main() { - - loop { - let mut reader = BufReader::new(io::stdin()); - let val = bc::parse_bencode(&mut reader); - match val { - Ok(res) => { - match res { - Some(val) => { - handle_incoming(val) - } - None => { - - } - } - - } - Err(bc::BencodeError::Eof()) => { - return - }, - Err(v) => panic!("{}", v) - } - - } -}