Skip to content

Commit

Permalink
Fixed surprising behavior with relative paths.
Browse files Browse the repository at this point in the history
  • Loading branch information
francesca64 committed Jul 22, 2017
1 parent 92f5b09 commit 1527b1e
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 12 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# 0.3

This release includes a non-breaking API change and a potentially breaking behavior change.

- `Hotwatch::watch` now accepts any path type that satisfies `AsRef<Path>`.
- Paths are automatically canonicalized. This is to prevent surprising behavior with handler matching. As a result of this, the paths enclosed in `hotwatch::Event` variants are now absolute, which can potentially break existing applications.

# 0.2

This release includes significant breaking API changes.

- Updated to notify 4.0.
- `hotwatch::Event` is now merely an alias for `notify::DebouncedEvent`, as it's a very nice type with even nicer documentation.
- `Hotwatch::watch` has become more powerful, but potentially more surprising; when watching a directory, the handler will now receive events for all contents, recursing into subdirectories. However, if any of those directory contents have their own handlers, only the most specific applicable handle will be fired. You can read about this in the [documentation](https://francesca64.github.io/hotwatch/docs/hotwatch/struct.Hotwatch.html#method.watch).
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hotwatch"
version = "0.2.1"
version = "0.3.0"
authors = ["Francesca Frangipane <[email protected]>"]
description = "A Rust library for conveniently watching and handling file changes."
documentation = "https://francesca64.github.io/hotwatch/docs/hotwatch"
Expand All @@ -11,5 +11,6 @@ keywords = ["notify", "watch", "events", "filesystem"]
license = "MIT"

[dependencies]
derive_more = "0.6"
notify = "4.0"
parking_lot = "0.4"
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2016 Francesca Frangipane
Copyright (c) 2016, 2017 Francesca Frangipane

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
30 changes: 20 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! hotwatch is a Rust library for comfortably watching and handling file changes.
//! hotwatch is a Rust library for comfortably watching and handling file changes.
//! It's a thin convenience wrapper over [notify](https://github.com/passcod/notify), allowing you to easily spawn handlers.
//!
//! Watching is done on a separate thread to avoid blocking your enjoyment of life.
Expand All @@ -9,11 +9,13 @@
#![feature(box_syntax)]

#[macro_use] extern crate derive_more;
extern crate notify;
extern crate parking_lot;

use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::fs::canonicalize;
use std::sync::Arc;
use std::sync::mpsc::{channel, Receiver};
use std::time::Duration;
Expand All @@ -36,7 +38,7 @@ fn path_from_event(e: &Event) -> Option<PathBuf> {
}
}

#[derive(Debug)]
#[derive(Debug, From)]
pub enum Error {
Io(std::io::Error),
Notify(notify::Error)
Expand All @@ -45,7 +47,7 @@ pub enum Error {
type HotwatchResult<T> = Result<T, Error>;

type Handler = Box<Fn(Event) + Send>;
type HandlerMapMutex = Arc<Mutex<HashMap<String, Handler>>>;
type HandlerMapMutex = Arc<Mutex<HashMap<PathBuf, Handler>>>;

pub struct Hotwatch {
watcher: RecommendedWatcher,
Expand Down Expand Up @@ -109,16 +111,20 @@ impl Hotwatch {
/// }
/// }).expect("Failed to watch file!");
/// ```
pub fn watch<F>(&mut self, path: &str, handler: F) -> HotwatchResult<()>
where F: 'static + Fn(Event) + Send {
pub fn watch<P, F>(&mut self, path: P, handler: F) -> HotwatchResult<()>
where P: AsRef<Path>, F: 'static + Fn(Event) + Send {
let absolute_path = canonicalize(path)?;
let mut handlers = self.handler_map_mutex.lock();
self.watcher.watch(Path::new(path), RecursiveMode::Recursive)
self.watcher.watch(Path::new(&absolute_path), RecursiveMode::Recursive)
.map_err(|e| match e {
notify::Error::Io(e) => Error::Io(e),
_ => Error::Notify(e)
})
.map(|_| {
(*handlers).insert(path.to_string(), box handler);
(*handlers).insert(PathBuf::from(absolute_path), box handler);
if cfg!(debug_assertions) {
println!("HotwatchHandlers {:?}", handlers.keys());
}
})
}

Expand All @@ -128,16 +134,20 @@ impl Hotwatch {
match rx.recv() {
Ok(event) => {
if cfg!(debug_assertions) {
println!("Hotwatch {:?}", event);
println!("HotwatchEvent {:?}", event);
}
let handlers = handler_map_mutex.lock();
if let Some(mut path) = path_from_event(&event) {
let mut handler = None;
let mut poppable = true;
if cfg!(debug_assertions) {
println!("HotwatchMatch");
}
while handler.is_none() && poppable {
if let Some(str_path) = path.to_str() {
handler = (*handlers).get(str_path);
if cfg!(debug_assertions) {
println!(" -> {:?}", path);
}
handler = (*handlers).get(&path);
poppable = path.pop();
}
if let Some(handler) = handler {
Expand Down

0 comments on commit 1527b1e

Please sign in to comment.