mirror of
https://github.com/extrawurst/gitui.git
synced 2024-12-26 18:43:37 +03:00
parent
5f7213730b
commit
cf9ce9d4ff
91
Cargo.lock
generated
91
Cargo.lock
generated
@ -455,6 +455,18 @@ dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetreelist"
|
||||
version = "0.5.0"
|
||||
@ -502,6 +514,15 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fsevent-sys"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.24"
|
||||
@ -673,6 +694,8 @@ dependencies = [
|
||||
"gh-emoji",
|
||||
"itertools",
|
||||
"log",
|
||||
"notify",
|
||||
"notify-debouncer-mini",
|
||||
"once_cell",
|
||||
"pprof",
|
||||
"pretty_assertions",
|
||||
@ -764,6 +787,26 @@ dependencies = [
|
||||
"str_stack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
@ -816,6 +859,26 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d6112e8f37b59803ac47a42d14f1f3a59bbf72fc6857ffc5be455e28a691f8e"
|
||||
dependencies = [
|
||||
"kqueue-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue-sys"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@ -955,6 +1018,34 @@ version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossbeam-channel",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
"libc",
|
||||
"mio",
|
||||
"walkdir",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-debouncer-mini"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c538ea1dd436b41e751922510cfbcaea2def87ed6ed94aa1edc15dc31b4c179"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"notify",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-format"
|
||||
version = "0.4.0"
|
||||
|
@ -37,6 +37,8 @@ fuzzy-matcher = "0.3"
|
||||
gh-emoji = { version = "1.0", optional = true }
|
||||
itertools = "0.10"
|
||||
log = "0.4"
|
||||
notify = "5.0"
|
||||
notify-debouncer-mini = "0.2"
|
||||
once_cell = "1"
|
||||
rayon-core = "1.9"
|
||||
ron = "0.8"
|
||||
|
@ -4,7 +4,9 @@ allow = [
|
||||
"MIT",
|
||||
"Apache-2.0",
|
||||
"BSD-2-Clause",
|
||||
"BSD-3-Clause"
|
||||
"BSD-3-Clause",
|
||||
"CC0-1.0",
|
||||
"ISC"
|
||||
]
|
||||
copyleft = "warn"
|
||||
allow-osi-fsf-free = "neither"
|
||||
|
@ -110,7 +110,7 @@ impl App {
|
||||
theme: Theme,
|
||||
key_config: KeyConfig,
|
||||
) -> Self {
|
||||
log::trace!("open repo at: {:?}", repo);
|
||||
log::trace!("open repo at: {:?}", &repo);
|
||||
|
||||
let queue = Queue::new();
|
||||
let theme = Rc::new(theme);
|
||||
|
25
src/main.rs
25
src/main.rs
@ -36,11 +36,15 @@ mod strings;
|
||||
mod tabs;
|
||||
mod ui;
|
||||
mod version;
|
||||
mod watcher;
|
||||
|
||||
use crate::{app::App, args::process_cmdline};
|
||||
use anyhow::{bail, Result};
|
||||
use app::QuitState;
|
||||
use asyncgit::{sync::RepoPath, AsyncGitNotification};
|
||||
use asyncgit::{
|
||||
sync::{utils::repo_work_dir, RepoPath},
|
||||
AsyncGitNotification,
|
||||
};
|
||||
use backtrace::Backtrace;
|
||||
use crossbeam_channel::{tick, unbounded, Receiver, Select};
|
||||
use crossterm::{
|
||||
@ -67,14 +71,14 @@ use tui::{
|
||||
Terminal,
|
||||
};
|
||||
use ui::style::Theme;
|
||||
use watcher::RepoWatcher;
|
||||
|
||||
static TICK_INTERVAL: Duration = Duration::from_secs(5);
|
||||
static SPINNER_INTERVAL: Duration = Duration::from_millis(80);
|
||||
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub enum QueueEvent {
|
||||
Tick,
|
||||
Notify,
|
||||
SpinnerUpdate,
|
||||
AsyncEvent(AsyncNotification),
|
||||
InputEvent(InputEvent),
|
||||
@ -161,7 +165,8 @@ fn run_app(
|
||||
let (tx_app, rx_app) = unbounded();
|
||||
|
||||
let rx_input = input.receiver();
|
||||
let ticker = tick(TICK_INTERVAL);
|
||||
let watcher = RepoWatcher::new(repo_work_dir(&repo)?.as_str())?;
|
||||
let rx_watcher = watcher.receiver();
|
||||
let spinner_ticker = tick(SPINNER_INTERVAL);
|
||||
|
||||
let mut app = App::new(
|
||||
@ -179,13 +184,13 @@ fn run_app(
|
||||
loop {
|
||||
let event = if first_update {
|
||||
first_update = false;
|
||||
QueueEvent::Tick
|
||||
QueueEvent::Notify
|
||||
} else {
|
||||
select_event(
|
||||
&rx_input,
|
||||
&rx_git,
|
||||
&rx_app,
|
||||
&ticker,
|
||||
&rx_watcher,
|
||||
&spinner_ticker,
|
||||
)?
|
||||
};
|
||||
@ -208,7 +213,7 @@ fn run_app(
|
||||
}
|
||||
app.event(ev)?;
|
||||
}
|
||||
QueueEvent::Tick => app.update()?,
|
||||
QueueEvent::Notify => app.update()?,
|
||||
QueueEvent::AsyncEvent(ev) => {
|
||||
if !matches!(
|
||||
ev,
|
||||
@ -282,7 +287,7 @@ fn select_event(
|
||||
rx_input: &Receiver<InputEvent>,
|
||||
rx_git: &Receiver<AsyncGitNotification>,
|
||||
rx_app: &Receiver<AsyncAppNotification>,
|
||||
rx_ticker: &Receiver<Instant>,
|
||||
rx_notify: &Receiver<()>,
|
||||
rx_spinner: &Receiver<Instant>,
|
||||
) -> Result<QueueEvent> {
|
||||
let mut sel = Select::new();
|
||||
@ -290,7 +295,7 @@ fn select_event(
|
||||
sel.recv(rx_input);
|
||||
sel.recv(rx_git);
|
||||
sel.recv(rx_app);
|
||||
sel.recv(rx_ticker);
|
||||
sel.recv(rx_notify);
|
||||
sel.recv(rx_spinner);
|
||||
|
||||
let oper = sel.select();
|
||||
@ -304,7 +309,7 @@ fn select_event(
|
||||
2 => oper.recv(rx_app).map(|e| {
|
||||
QueueEvent::AsyncEvent(AsyncNotification::App(e))
|
||||
}),
|
||||
3 => oper.recv(rx_ticker).map(|_| QueueEvent::Tick),
|
||||
3 => oper.recv(rx_notify).map(|_| QueueEvent::Notify),
|
||||
4 => oper.recv(rx_spinner).map(|_| QueueEvent::SpinnerUpdate),
|
||||
_ => bail!("unknown select source"),
|
||||
}?;
|
||||
|
70
src/watcher.rs
Normal file
70
src/watcher.rs
Normal file
@ -0,0 +1,70 @@
|
||||
use anyhow::Result;
|
||||
use crossbeam_channel::{unbounded, Sender};
|
||||
use notify::{Error, RecommendedWatcher, RecursiveMode};
|
||||
use notify_debouncer_mini::{
|
||||
new_debouncer, DebouncedEvent, Debouncer,
|
||||
};
|
||||
use std::{
|
||||
path::Path, sync::mpsc::RecvError, thread, time::Duration,
|
||||
};
|
||||
|
||||
pub struct RepoWatcher {
|
||||
receiver: crossbeam_channel::Receiver<()>,
|
||||
#[allow(dead_code)]
|
||||
debouncer: Debouncer<RecommendedWatcher>,
|
||||
}
|
||||
|
||||
impl RepoWatcher {
|
||||
pub fn new(workdir: &str) -> Result<Self> {
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
|
||||
let mut debouncer =
|
||||
new_debouncer(Duration::from_secs(2), None, tx)?;
|
||||
|
||||
debouncer
|
||||
.watcher()
|
||||
.watch(Path::new(workdir), RecursiveMode::Recursive)?;
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
debouncer,
|
||||
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<(), RecvError> {
|
||||
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(()).expect("send error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user