bumb dependencies

This commit is contained in:
Robin Appelman 2023-06-29 17:44:19 +02:00
commit 7430db6c5b
5 changed files with 758 additions and 326 deletions

1039
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -5,16 +5,18 @@ authors = ["Robin Appelman <robin@icewind.nl>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
notify = "4.0" notify = "6.0"
redis = { version = "0.20", default-features = false } notify-debouncer-full = "0.2.0"
redis = { version = "0.23", default-features = false }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
color-eyre = "0.5" color-eyre = "0.6"
clap = { version = "4.3.9", features = ["derive"] }
[dev-dependencies] [dev-dependencies]
rand = "0.8.3" rand = "0.8.5"
tempfile = "3" tempfile = "3"
[profile.release] [profile.release]
lto = true lto = true

View file

@ -1,6 +1,8 @@
use chrono::{DateTime, Timelike, Utc}; use chrono::{DateTime, Timelike, Utc};
use color_eyre::{eyre::WrapErr, Result}; use color_eyre::{eyre::WrapErr, Result};
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use notify::event::{ModifyKind, RenameMode};
use notify::{EventKind, RecursiveMode, Watcher};
use notify_debouncer_full::{new_debouncer, DebouncedEvent};
use redis::{Client, Commands, Connection, IntoConnectionInfo}; use redis::{Client, Commands, Connection, IntoConnectionInfo};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -31,12 +33,23 @@ impl From<DebouncedEvent> for Event {
fn from(event: DebouncedEvent) -> Self { fn from(event: DebouncedEvent) -> Self {
let time = Utc::now().with_nanosecond(0).unwrap(); let time = Utc::now().with_nanosecond(0).unwrap();
match event { let path_count = event.paths.len();
DebouncedEvent::Write(path) let mut paths = event.event.paths.into_iter();
| DebouncedEvent::Create(path)
| DebouncedEvent::Chmod(path) => Event::Modify { path, time }, match (event.event.kind, path_count) {
DebouncedEvent::Rename(from, to) => Event::Move { from, to, time }, (EventKind::Modify(ModifyKind::Name(RenameMode::Both)), 2..) => Event::Move {
DebouncedEvent::Remove(path) => Event::Delete { path, time }, from: paths.next().unwrap(),
to: paths.next().unwrap(),
time,
},
(EventKind::Modify(_) | EventKind::Create(_), 1..) => Event::Modify {
path: paths.next().unwrap(),
time,
},
(EventKind::Remove(_), 1..) => Event::Delete {
path: paths.next().unwrap(),
time,
},
_ => Event::None, _ => Event::None,
} }
} }
@ -50,16 +63,20 @@ pub fn watch(
) -> Result<()> { ) -> Result<()> {
let (tx, rx) = channel(); let (tx, rx) = channel();
let mut watcher: RecommendedWatcher = Watcher::new(tx, debounce)?; let mut watcher = new_debouncer(debounce, None, tx)?;
let client = Client::open(redis_connect).wrap_err("Invalid redis connection")?; let client = Client::open(redis_connect).wrap_err("Invalid redis connection")?;
let mut con = client let mut con = client
.get_connection() .get_connection()
.wrap_err("Failed to open redis connection")?; .wrap_err("Failed to open redis connection")?;
watcher.watch(path, RecursiveMode::Recursive)?; watcher
.watcher()
.watch(path.as_ref(), RecursiveMode::Recursive)?;
while let Ok(event) = rx.recv() { while let Ok(event) = rx.recv() {
push_event(event, &mut con, redis_list).wrap_err("Failed to send event to redis")?; for event in event.into_iter().flatten() {
push_event(event, &mut con, redis_list).wrap_err("Failed to send event to redis")?;
}
} }
Ok(()) Ok(())
} }

View file

@ -1,14 +1,28 @@
use clap::Parser;
use color_eyre::Result; use color_eyre::Result;
use notify_redis::watch; use notify_redis::watch;
use std::env; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
/// Push filesystem notifications into a redis list
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Folder to watch
path: PathBuf,
/// Redis connection string
redis_connect: String,
/// Redis list to push changes to
redis_list: String,
}
fn main() -> Result<()> { fn main() -> Result<()> {
let args: Vec<_> = env::args().collect(); let args: Args = Args::parse();
if let [_, path, redis, list] = args.as_slice() { watch(
watch(path, redis.as_str(), list, Duration::from_secs(2))?; args.path,
} else { args.redis_connect,
println!("usage: {} <path> <redis_connect> <redis_list>", args[0]) &args.redis_list,
} Duration::from_secs(2),
)?;
Ok(()) Ok(())
} }

View file

@ -28,7 +28,7 @@ impl EventList {
} }
fn next(&mut self) -> Option<Event> { fn next(&mut self) -> Option<Event> {
let raw: Option<String> = self.redis.rpop(&self.list).unwrap(); let raw: Option<String> = self.redis.rpop(&self.list, None).unwrap();
raw.map(|raw| serde_json::from_str(&raw).unwrap()) raw.map(|raw| serde_json::from_str(&raw).unwrap())
} }
} }