mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-25 15:16:07 +00:00
Break out file watching into FsWatcher object
This commit is contained in:
118
server/src/fs_watcher.rs
Normal file
118
server/src/fs_watcher.rs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
use std::{
|
||||||
|
sync::{mpsc, Arc, Mutex},
|
||||||
|
time::Duration,
|
||||||
|
thread,
|
||||||
|
};
|
||||||
|
|
||||||
|
use notify::{
|
||||||
|
self,
|
||||||
|
DebouncedEvent,
|
||||||
|
RecommendedWatcher,
|
||||||
|
RecursiveMode,
|
||||||
|
Watcher,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
vfs::Vfs,
|
||||||
|
rbx_session::RbxSession,
|
||||||
|
};
|
||||||
|
|
||||||
|
const WATCH_TIMEOUT: Duration = Duration::from_millis(100);
|
||||||
|
|
||||||
|
fn handle_event(vfs: &Mutex<Vfs>, rbx_session: &Mutex<RbxSession>, event: DebouncedEvent) {
|
||||||
|
match event {
|
||||||
|
DebouncedEvent::Create(path) => {
|
||||||
|
{
|
||||||
|
let mut vfs = vfs.lock().unwrap();
|
||||||
|
vfs.path_created(&path).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut rbx_session = rbx_session.lock().unwrap();
|
||||||
|
rbx_session.path_created(&path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DebouncedEvent::Write(path) => {
|
||||||
|
{
|
||||||
|
let mut vfs = vfs.lock().unwrap();
|
||||||
|
vfs.path_updated(&path).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut rbx_session = rbx_session.lock().unwrap();
|
||||||
|
rbx_session.path_updated(&path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DebouncedEvent::Remove(path) => {
|
||||||
|
{
|
||||||
|
let mut vfs = vfs.lock().unwrap();
|
||||||
|
vfs.path_removed(&path).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut rbx_session = rbx_session.lock().unwrap();
|
||||||
|
rbx_session.path_removed(&path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DebouncedEvent::Rename(from_path, to_path) => {
|
||||||
|
{
|
||||||
|
let mut vfs = vfs.lock().unwrap();
|
||||||
|
vfs.path_moved(&from_path, &to_path).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut rbx_session = rbx_session.lock().unwrap();
|
||||||
|
rbx_session.path_renamed(&from_path, &to_path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Watches for changes on the filesystem and links together the in-memory
|
||||||
|
/// filesystem and in-memory Roblox tree.
|
||||||
|
pub struct FsWatcher {
|
||||||
|
#[allow(unused)]
|
||||||
|
watchers: Vec<RecommendedWatcher>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FsWatcher {
|
||||||
|
pub fn start(vfs: Arc<Mutex<Vfs>>, rbx_session: Arc<Mutex<RbxSession>>) -> FsWatcher {
|
||||||
|
let mut watchers = Vec::new();
|
||||||
|
|
||||||
|
{
|
||||||
|
let vfs_temp = vfs.lock().unwrap();
|
||||||
|
|
||||||
|
for root_path in vfs_temp.get_roots() {
|
||||||
|
let (watch_tx, watch_rx) = mpsc::channel();
|
||||||
|
|
||||||
|
let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT)
|
||||||
|
.expect("Could not create `notify` watcher");
|
||||||
|
|
||||||
|
watcher.watch(root_path, RecursiveMode::Recursive)
|
||||||
|
.expect("Could not watch directory");
|
||||||
|
|
||||||
|
watchers.push(watcher);
|
||||||
|
|
||||||
|
let vfs = Arc::clone(&vfs);
|
||||||
|
let rbx_session = Arc::clone(&rbx_session);
|
||||||
|
let root_path = root_path.clone();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
info!("Watcher thread ({}) started", root_path.display());
|
||||||
|
loop {
|
||||||
|
match watch_rx.recv() {
|
||||||
|
Ok(event) => handle_event(&vfs, &rbx_session, event),
|
||||||
|
Err(_) => break,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
info!("Watcher thread ({}) stopped", root_path.display());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FsWatcher {
|
||||||
|
watchers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ extern crate tempfile;
|
|||||||
|
|
||||||
// pub mod roblox_studio;
|
// pub mod roblox_studio;
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
pub mod fs_watcher;
|
||||||
pub mod message_queue;
|
pub mod message_queue;
|
||||||
pub mod project;
|
pub mod project;
|
||||||
pub mod rbx_session;
|
pub mod rbx_session;
|
||||||
|
|||||||
@@ -1,16 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, Mutex, mpsc},
|
sync::{Arc, Mutex},
|
||||||
thread,
|
|
||||||
io,
|
io,
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use notify::{
|
|
||||||
self,
|
|
||||||
DebouncedEvent,
|
|
||||||
RecommendedWatcher,
|
|
||||||
RecursiveMode,
|
|
||||||
Watcher,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -19,17 +9,15 @@ use crate::{
|
|||||||
vfs::Vfs,
|
vfs::Vfs,
|
||||||
session_id::SessionId,
|
session_id::SessionId,
|
||||||
rbx_session::RbxSession,
|
rbx_session::RbxSession,
|
||||||
|
fs_watcher::FsWatcher,
|
||||||
};
|
};
|
||||||
|
|
||||||
const WATCH_TIMEOUT_MS: u64 = 100;
|
|
||||||
|
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub project: Arc<Project>,
|
pub project: Arc<Project>,
|
||||||
pub session_id: SessionId,
|
pub session_id: SessionId,
|
||||||
pub message_queue: Arc<MessageQueue>,
|
pub message_queue: Arc<MessageQueue>,
|
||||||
pub rbx_session: Arc<Mutex<RbxSession>>,
|
pub rbx_session: Arc<Mutex<RbxSession>>,
|
||||||
vfs: Arc<Mutex<Vfs>>,
|
fs_watcher: FsWatcher,
|
||||||
watchers: Vec<RecommendedWatcher>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> {
|
fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> {
|
||||||
@@ -49,15 +37,14 @@ fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()>
|
|||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
pub fn new(project: Project) -> io::Result<Session> {
|
pub fn new(project: Project) -> io::Result<Session> {
|
||||||
|
let mut vfs = Vfs::new();
|
||||||
|
|
||||||
|
add_sync_points(&mut vfs, &project.tree)
|
||||||
|
.expect("Could not add sync points when starting new Rojo session");
|
||||||
|
|
||||||
|
let vfs = Arc::new(Mutex::new(vfs));
|
||||||
let project = Arc::new(project);
|
let project = Arc::new(project);
|
||||||
let message_queue = Arc::new(MessageQueue::new());
|
let message_queue = Arc::new(MessageQueue::new());
|
||||||
let vfs = Arc::new(Mutex::new(Vfs::new()));
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut vfs = vfs.lock().unwrap();
|
|
||||||
add_sync_points(&mut vfs, &project.tree)
|
|
||||||
.expect("Could not add sync points when starting new Rojo session");
|
|
||||||
}
|
|
||||||
|
|
||||||
let rbx_session = Arc::new(Mutex::new(RbxSession::new(
|
let rbx_session = Arc::new(Mutex::new(RbxSession::new(
|
||||||
Arc::clone(&project),
|
Arc::clone(&project),
|
||||||
@@ -65,95 +52,19 @@ impl Session {
|
|||||||
Arc::clone(&message_queue),
|
Arc::clone(&message_queue),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let mut watchers = Vec::new();
|
let fs_watcher = FsWatcher::start(
|
||||||
|
Arc::clone(&vfs),
|
||||||
{
|
Arc::clone(&rbx_session),
|
||||||
let vfs_temp = vfs.lock().unwrap();
|
);
|
||||||
|
|
||||||
for root in vfs_temp.get_roots() {
|
|
||||||
info!("Watching path {}", root.display());
|
|
||||||
|
|
||||||
let (watch_tx, watch_rx) = mpsc::channel();
|
|
||||||
|
|
||||||
let mut watcher = notify::watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap();
|
|
||||||
|
|
||||||
watcher.watch(root, RecursiveMode::Recursive)
|
|
||||||
.expect("Could not watch directory");
|
|
||||||
|
|
||||||
watchers.push(watcher);
|
|
||||||
|
|
||||||
let vfs = Arc::clone(&vfs);
|
|
||||||
let rbx_session = Arc::clone(&rbx_session);
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
loop {
|
|
||||||
match watch_rx.recv() {
|
|
||||||
Ok(event) => {
|
|
||||||
match event {
|
|
||||||
DebouncedEvent::Create(path) => {
|
|
||||||
{
|
|
||||||
let mut vfs = vfs.lock().unwrap();
|
|
||||||
vfs.path_created(&path).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut rbx_session = rbx_session.lock().unwrap();
|
|
||||||
rbx_session.path_created(&path);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DebouncedEvent::Write(path) => {
|
|
||||||
{
|
|
||||||
let mut vfs = vfs.lock().unwrap();
|
|
||||||
vfs.path_updated(&path).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut rbx_session = rbx_session.lock().unwrap();
|
|
||||||
rbx_session.path_updated(&path);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DebouncedEvent::Remove(path) => {
|
|
||||||
{
|
|
||||||
let mut vfs = vfs.lock().unwrap();
|
|
||||||
vfs.path_removed(&path).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut rbx_session = rbx_session.lock().unwrap();
|
|
||||||
rbx_session.path_removed(&path);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DebouncedEvent::Rename(from_path, to_path) => {
|
|
||||||
{
|
|
||||||
let mut vfs = vfs.lock().unwrap();
|
|
||||||
vfs.path_moved(&from_path, &to_path).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut rbx_session = rbx_session.lock().unwrap();
|
|
||||||
rbx_session.path_renamed(&from_path, &to_path);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
Err(_) => break,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
info!("Watcher thread stopped");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let session_id = SessionId::new();
|
let session_id = SessionId::new();
|
||||||
|
|
||||||
Ok(Session {
|
Ok(Session {
|
||||||
session_id,
|
|
||||||
rbx_session,
|
|
||||||
project,
|
project,
|
||||||
|
session_id,
|
||||||
message_queue,
|
message_queue,
|
||||||
vfs,
|
rbx_session,
|
||||||
watchers,
|
fs_watcher,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user