add git watcher

This commit is contained in:
Nikita Galaiko 2023-03-14 11:30:58 +01:00
parent 3abded40ff
commit 1f4c96f827
No known key found for this signature in database
GPG Key ID: EBAB54E845BA519D
3 changed files with 116 additions and 2 deletions

View File

@ -136,7 +136,7 @@ impl DeltaWatchers {
Ok(())
}
pub fn unwatch(&mut self, project: projects::Project) -> Result<()> {
pub fn unwatch(&mut self, project: &projects::Project) -> Result<()> {
if let Some(mut watcher) = self.watchers.remove(&project.path) {
watcher.unwatch(Path::new(&project.path))?;
}

View File

@ -0,0 +1,108 @@
use crate::projects;
use anyhow::Result;
use notify::{Config, RecommendedWatcher, Watcher};
use std::{
collections::HashMap,
path::Path,
sync::{mpsc, Arc, Mutex},
};
pub enum Event {
Head,
}
pub struct GitWatchers {
watchers: HashMap<String, RecommendedWatcher>,
}
impl GitWatchers {
pub fn new() -> Self {
Self {
watchers: HashMap::new(),
}
}
pub fn unwatch(&mut self, project: &projects::Project) -> Result<()> {
if let Some(mut watcher) = self.watchers.remove(&project.id) {
watcher.unwatch(&Path::new(&Path::new(&project.path).join(".git")))?;
}
Ok(())
}
pub fn watch(&mut self, project: projects::Project) -> Result<mpsc::Receiver<Event>> {
let (tx, rx) = mpsc::channel();
let mut watcher = RecommendedWatcher::new(tx, Config::default())?;
watcher.watch(
Path::new(&Path::new(&project.path).join(".git")),
notify::RecursiveMode::Recursive,
)?;
self.watchers.insert(project.id.clone(), watcher);
let project = Arc::new(Mutex::new(project.clone()));
let (events_sender, events_receiver) = mpsc::channel();
tauri::async_runtime::spawn_blocking(move || {
log::info!("{}: watching git", project.lock().unwrap().id);
let project = project.lock().unwrap().clone();
let project_path = Path::new(&project.path);
while let Ok(event) = rx.recv() {
if let Err(e) = event {
log::error!("{}: notify event error: {:#}", project.id.clone(), e);
continue;
}
let event = event.unwrap();
for file_path in event.paths {
let relative_file_path = file_path
.strip_prefix(Path::new(&project_path.join(".git")))
.unwrap();
match is_interesting_event(&event.kind) {
Some(kind_string) => {
log::info!(
"{}: \"{}\" {}",
project.id,
relative_file_path.display(),
kind_string
);
if relative_file_path == Path::new("HEAD") {
if let Err(e) = events_sender.send(Event::Head) {
log::error!("{}: failed to send event: {:#}", project.id, e);
}
}
}
None => {
// ignore
}
}
}
}
log::info!("{}: stopped watching git", project.id);
});
Ok(events_receiver)
}
}
fn is_interesting_event(kind: &notify::EventKind) -> Option<String> {
match kind {
notify::EventKind::Create(notify::event::CreateKind::File) => {
Some("file created".to_string())
}
notify::EventKind::Modify(notify::event::ModifyKind::Data(_)) => {
Some("file modified".to_string())
}
notify::EventKind::Modify(notify::event::ModifyKind::Name(_)) => {
Some("file renamed".to_string())
}
notify::EventKind::Remove(notify::event::RemoveKind::File) => {
Some("file removed".to_string())
}
_ => None,
}
}

View File

@ -1,4 +1,5 @@
mod delta;
mod git;
mod session;
#[cfg(test)]
@ -16,6 +17,7 @@ use std::{
pub struct Watcher {
session_watcher: session::SessionWatcher,
delta_watcher: delta::DeltaWatchers,
git_watcher: git::GitWatchers,
}
impl Watcher {
@ -27,9 +29,11 @@ impl Watcher {
let session_watcher =
session::SessionWatcher::new(projects_storage, users_storage, deltas_searcher);
let delta_watcher = delta::DeltaWatchers::new();
let git_watcher = git::GitWatchers::new();
Self {
session_watcher,
delta_watcher,
git_watcher,
}
}
@ -53,12 +57,14 @@ impl Watcher {
.watch(sender.clone(), project.clone(), lock_file.clone())?;
self.session_watcher
.watch(sender.clone(), project.clone(), lock_file.clone())?;
self.git_watcher.watch(project.clone())?;
Ok(())
}
pub fn unwatch(&mut self, project: projects::Project) -> Result<()> {
self.delta_watcher.unwatch(project)?;
self.delta_watcher.unwatch(&project)?;
self.git_watcher.unwatch(&project)?;
// TODO: how to unwatch session ?
Ok(())
}