mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
* Default to tick-based updates This commit reintroduces code that was previously removed in favor of a notify-based update trigger. It turned out that notify-based updates can cause issues in larger repositories, so tick-based updates seemed like a safer default. https://github.com/extrawurst/gitui/issues/1444 https://github.com/extrawurst/gitui/pull/1310 * Add FAQ entry for --watcher * Remove --poll
86 lines
1.8 KiB
Rust
86 lines
1.8 KiB
Rust
use anyhow::Result;
|
|
use crossbeam_channel::{unbounded, Sender};
|
|
use notify::{Error, RecommendedWatcher, RecursiveMode, Watcher};
|
|
use notify_debouncer_mini::{new_debouncer, DebouncedEvent};
|
|
use scopetime::scope_time;
|
|
use std::{path::Path, thread, time::Duration};
|
|
|
|
pub struct RepoWatcher {
|
|
receiver: crossbeam_channel::Receiver<()>,
|
|
}
|
|
|
|
impl RepoWatcher {
|
|
pub fn new(workdir: &str) -> Self {
|
|
log::trace!(
|
|
"recommended watcher: {:?}",
|
|
RecommendedWatcher::kind()
|
|
);
|
|
|
|
let (tx, rx) = std::sync::mpsc::channel();
|
|
|
|
let workdir = workdir.to_string();
|
|
|
|
thread::spawn(move || {
|
|
let timeout = Duration::from_secs(2);
|
|
create_watcher(timeout, tx, &workdir);
|
|
});
|
|
|
|
let (out_tx, out_rx) = unbounded();
|
|
|
|
thread::spawn(move || {
|
|
if let Err(e) = Self::forwarder(&rx, &out_tx) {
|
|
//maybe we need to restart the forwarder now?
|
|
log::error!("notify receive error: {}", e);
|
|
}
|
|
});
|
|
|
|
Self { receiver: out_rx }
|
|
}
|
|
|
|
///
|
|
pub fn receiver(&self) -> crossbeam_channel::Receiver<()> {
|
|
self.receiver.clone()
|
|
}
|
|
|
|
fn forwarder(
|
|
receiver: &std::sync::mpsc::Receiver<
|
|
Result<Vec<DebouncedEvent>, Vec<Error>>,
|
|
>,
|
|
sender: &Sender<()>,
|
|
) -> Result<()> {
|
|
loop {
|
|
let ev = receiver.recv()?;
|
|
|
|
if let Ok(ev) = ev {
|
|
log::debug!("notify events: {}", ev.len());
|
|
|
|
for (idx, ev) in ev.iter().enumerate() {
|
|
log::debug!("notify [{}]: {:?}", idx, ev);
|
|
}
|
|
|
|
if !ev.is_empty() {
|
|
sender.send(())?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn create_watcher(
|
|
timeout: Duration,
|
|
tx: std::sync::mpsc::Sender<
|
|
Result<Vec<DebouncedEvent>, Vec<Error>>,
|
|
>,
|
|
workdir: &str,
|
|
) {
|
|
scope_time!("create_watcher");
|
|
|
|
let mut bouncer =
|
|
new_debouncer(timeout, None, tx).expect("Watch create error");
|
|
bouncer
|
|
.watcher()
|
|
.watch(Path::new(&workdir), RecursiveMode::Recursive)
|
|
.expect("Watch error");
|
|
|
|
std::mem::forget(bouncer);
|
|
}
|