Watch non-canonical path for config symlinks
To make it possible to detect the replacement of the configuration file when it is a symlink, the symlinks path has to be observed in addition to the canonicalized path. That way changes to either file will trigger a live config reload. Multiple layers of symlinks would still not get detected when any symlink other than the configuration file itself is replaced, but this patch should cover most realistic usage scenarios.
This commit is contained in:
parent
e6565f1b76
commit
70d3b4ef6c
|
@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
- `ExpandSelection` is now a configurable mouse binding action
|
||||
- Config option `background_opacity`, you should use `window.opacity` instead
|
||||
- Reload configuration files when their symbolic link is replaced
|
||||
|
||||
## 0.9.0
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
@ -16,23 +15,21 @@ const DEBOUNCE_DELAY: Duration = Duration::from_millis(10);
|
|||
const DEBOUNCE_DELAY: Duration = Duration::from_millis(1000);
|
||||
|
||||
pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventProxy) {
|
||||
// Canonicalize all paths, filtering out the ones that do not exist.
|
||||
paths = paths
|
||||
.drain(..)
|
||||
.filter_map(|path| match fs::canonicalize(&path) {
|
||||
Ok(path) => Some(path),
|
||||
Err(err) => {
|
||||
error!("Unable to canonicalize config path {:?}: {}", path, err);
|
||||
None
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Don't monitor config if there is no path to watch.
|
||||
if paths.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Canonicalize paths, keeping the base paths for symlinks.
|
||||
for i in 0..paths.len() {
|
||||
if let Ok(canonical_path) = paths[i].canonicalize() {
|
||||
match paths[i].symlink_metadata() {
|
||||
Ok(metadata) if metadata.file_type().is_symlink() => paths.push(canonical_path),
|
||||
_ => paths[i] = canonical_path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The Duration argument is a debouncing period.
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let mut watcher = match watcher(tx, DEBOUNCE_DELAY) {
|
||||
|
@ -73,17 +70,15 @@ pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventProxy) {
|
|||
};
|
||||
|
||||
match event {
|
||||
DebouncedEvent::Rename(..) => continue,
|
||||
DebouncedEvent::Write(path)
|
||||
DebouncedEvent::Rename(_, path)
|
||||
| DebouncedEvent::Write(path)
|
||||
| DebouncedEvent::Create(path)
|
||||
| DebouncedEvent::Chmod(path) => {
|
||||
if !paths.contains(&path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
| DebouncedEvent::Chmod(path)
|
||||
if paths.contains(&path) =>
|
||||
{
|
||||
// Always reload the primary configuration file.
|
||||
event_proxy.send_event(Event::ConfigReload(paths[0].clone()));
|
||||
},
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue