Vfs -> Imfs, clean up and document a bit

This commit is contained in:
Lucien Greathouse
2018-11-17 13:51:22 -08:00
parent c8bb9bf2e9
commit 16c3c1f498
9 changed files with 67 additions and 66 deletions

10
server/Cargo.lock generated
View File

@@ -349,11 +349,8 @@ dependencies = [
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "libc" name = "libc"
@@ -698,6 +695,7 @@ version = "0.5.0"
dependencies = [ dependencies = [
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -875,7 +873,7 @@ name = "thread_local"
version = "0.3.6" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -1117,7 +1115,7 @@ dependencies = [
"checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c"
"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" "checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2"

View File

@@ -35,3 +35,4 @@ uuid = { version = "0.7", features = ["v4", "serde"] }
[dev-dependencies] [dev-dependencies]
tempfile = "3.0" tempfile = "3.0"
walkdir = "2.1" walkdir = "2.1"
lazy_static = "1.2"

View File

@@ -13,18 +13,18 @@ use notify::{
}; };
use crate::{ use crate::{
vfs::Vfs, imfs::Imfs,
rbx_session::RbxSession, rbx_session::RbxSession,
}; };
const WATCH_TIMEOUT: Duration = Duration::from_millis(100); const WATCH_TIMEOUT: Duration = Duration::from_millis(100);
fn handle_event(vfs: &Mutex<Vfs>, rbx_session: &Mutex<RbxSession>, event: DebouncedEvent) { fn handle_event(imfs: &Mutex<Imfs>, rbx_session: &Mutex<RbxSession>, event: DebouncedEvent) {
match event { match event {
DebouncedEvent::Create(path) => { DebouncedEvent::Create(path) => {
{ {
let mut vfs = vfs.lock().unwrap(); let mut imfs = imfs.lock().unwrap();
vfs.path_created(&path).unwrap(); imfs.path_created(&path).unwrap();
} }
{ {
@@ -34,8 +34,8 @@ fn handle_event(vfs: &Mutex<Vfs>, rbx_session: &Mutex<RbxSession>, event: Deboun
}, },
DebouncedEvent::Write(path) => { DebouncedEvent::Write(path) => {
{ {
let mut vfs = vfs.lock().unwrap(); let mut imfs = imfs.lock().unwrap();
vfs.path_updated(&path).unwrap(); imfs.path_updated(&path).unwrap();
} }
{ {
@@ -45,8 +45,8 @@ fn handle_event(vfs: &Mutex<Vfs>, rbx_session: &Mutex<RbxSession>, event: Deboun
}, },
DebouncedEvent::Remove(path) => { DebouncedEvent::Remove(path) => {
{ {
let mut vfs = vfs.lock().unwrap(); let mut imfs = imfs.lock().unwrap();
vfs.path_removed(&path).unwrap(); imfs.path_removed(&path).unwrap();
} }
{ {
@@ -56,8 +56,8 @@ fn handle_event(vfs: &Mutex<Vfs>, rbx_session: &Mutex<RbxSession>, event: Deboun
}, },
DebouncedEvent::Rename(from_path, to_path) => { DebouncedEvent::Rename(from_path, to_path) => {
{ {
let mut vfs = vfs.lock().unwrap(); let mut imfs = imfs.lock().unwrap();
vfs.path_moved(&from_path, &to_path).unwrap(); imfs.path_moved(&from_path, &to_path).unwrap();
} }
{ {
@@ -77,13 +77,13 @@ pub struct FsWatcher {
} }
impl FsWatcher { impl FsWatcher {
pub fn start(vfs: Arc<Mutex<Vfs>>, rbx_session: Arc<Mutex<RbxSession>>) -> FsWatcher { pub fn start(imfs: Arc<Mutex<Imfs>>, rbx_session: Arc<Mutex<RbxSession>>) -> FsWatcher {
let mut watchers = Vec::new(); let mut watchers = Vec::new();
{ {
let vfs_temp = vfs.lock().unwrap(); let imfs_temp = imfs.lock().unwrap();
for root_path in vfs_temp.get_roots() { for root_path in imfs_temp.get_roots() {
let (watch_tx, watch_rx) = mpsc::channel(); let (watch_tx, watch_rx) = mpsc::channel();
let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT) let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT)
@@ -94,7 +94,7 @@ impl FsWatcher {
watchers.push(watcher); watchers.push(watcher);
let vfs = Arc::clone(&vfs); let imfs = Arc::clone(&imfs);
let rbx_session = Arc::clone(&rbx_session); let rbx_session = Arc::clone(&rbx_session);
let root_path = root_path.clone(); let root_path = root_path.clone();
@@ -102,7 +102,7 @@ impl FsWatcher {
info!("Watcher thread ({}) started", root_path.display()); info!("Watcher thread ({}) started", root_path.display());
loop { loop {
match watch_rx.recv() { match watch_rx.recv() {
Ok(event) => handle_event(&vfs, &rbx_session, event), Ok(event) => handle_event(&imfs, &rbx_session, event),
Err(_) => break, Err(_) => break,
}; };
} }

View File

@@ -5,15 +5,18 @@ use std::{
io, io,
}; };
/// The in-memory filesystem keeps a mirror of all files being watcher by Rojo
/// in order to deduplicate file changes in the case of bidirectional syncing
/// from Roblox Studio.
#[derive(Debug)] #[derive(Debug)]
pub struct Vfs { pub struct Imfs {
items: HashMap<PathBuf, VfsItem>, items: HashMap<PathBuf, ImfsItem>,
roots: HashSet<PathBuf>, roots: HashSet<PathBuf>,
} }
impl Vfs { impl Imfs {
pub fn new() -> Vfs { pub fn new() -> Imfs {
Vfs { Imfs {
items: HashMap::new(), items: HashMap::new(),
roots: HashSet::new(), roots: HashSet::new(),
} }
@@ -23,7 +26,7 @@ impl Vfs {
&self.roots &self.roots
} }
pub fn get(&self, path: &Path) -> Option<&VfsItem> { pub fn get(&self, path: &Path) -> Option<&ImfsItem> {
debug_assert!(path.is_absolute()); debug_assert!(path.is_absolute());
debug_assert!(self.is_within_roots(path)); debug_assert!(self.is_within_roots(path));
@@ -36,7 +39,7 @@ impl Vfs {
self.roots.insert(path.to_path_buf()); self.roots.insert(path.to_path_buf());
VfsItem::read_from_disk(self, path)?; ImfsItem::read_from_disk(self, path)?;
Ok(()) Ok(())
} }
@@ -50,7 +53,7 @@ impl Vfs {
} }
} }
VfsItem::read_from_disk(self, path)?; ImfsItem::read_from_disk(self, path)?;
Ok(()) Ok(())
} }
@@ -64,7 +67,7 @@ impl Vfs {
} }
} }
VfsItem::read_from_disk(self, path)?; ImfsItem::read_from_disk(self, path)?;
Ok(()) Ok(())
} }
@@ -74,14 +77,14 @@ impl Vfs {
if let Some(parent_path) = path.parent() { if let Some(parent_path) = path.parent() {
if self.is_within_roots(parent_path) { if self.is_within_roots(parent_path) {
if let Some(VfsItem::Directory(parent)) = self.items.get_mut(parent_path) { if let Some(ImfsItem::Directory(parent)) = self.items.get_mut(parent_path) {
parent.children.remove(path); parent.children.remove(path);
} }
} }
} }
match self.items.remove(path) { match self.items.remove(path) {
Some(VfsItem::Directory(directory)) => { Some(ImfsItem::Directory(directory)) => {
for child_path in &directory.children { for child_path in &directory.children {
self.path_removed(child_path)?; self.path_removed(child_path)?;
} }
@@ -115,30 +118,30 @@ impl Vfs {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct VfsFile { pub struct ImfsFile {
pub path: PathBuf, pub path: PathBuf,
pub contents: Vec<u8>, pub contents: Vec<u8>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct VfsDirectory { pub struct ImfsDirectory {
pub path: PathBuf, pub path: PathBuf,
pub children: HashSet<PathBuf>, pub children: HashSet<PathBuf>,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum VfsItem { pub enum ImfsItem {
File(VfsFile), File(ImfsFile),
Directory(VfsDirectory), Directory(ImfsDirectory),
} }
impl VfsItem { impl ImfsItem {
fn read_from_disk<'a, 'b>(vfs: &'a mut Vfs, path: &'b Path) -> io::Result<&'a VfsItem> { fn read_from_disk<'a, 'b>(vfs: &'a mut Imfs, path: &'b Path) -> io::Result<&'a ImfsItem> {
let metadata = fs::metadata(path)?; let metadata = fs::metadata(path)?;
if metadata.is_file() { if metadata.is_file() {
let contents = fs::read(path)?; let contents = fs::read(path)?;
let item = VfsItem::File(VfsFile { let item = ImfsItem::File(ImfsFile {
path: path.to_path_buf(), path: path.to_path_buf(),
contents, contents,
}); });
@@ -153,12 +156,12 @@ impl VfsItem {
let entry = entry?; let entry = entry?;
let child_path = entry.path(); let child_path = entry.path();
VfsItem::read_from_disk(vfs, &child_path)?; ImfsItem::read_from_disk(vfs, &child_path)?;
children.insert(child_path); children.insert(child_path);
} }
let item = VfsItem::Directory(VfsDirectory { let item = ImfsItem::Directory(ImfsDirectory {
path: path.to_path_buf(), path: path.to_path_buf(),
children, children,
}); });

View File

@@ -20,6 +20,6 @@ pub mod project;
pub mod rbx_session; pub mod rbx_session;
pub mod session; pub mod session;
pub mod session_id; pub mod session_id;
pub mod vfs; pub mod imfs;
pub mod web; pub mod web;
pub mod web_util; pub mod web_util;

View File

@@ -10,7 +10,7 @@ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue};
use crate::{ use crate::{
project::{Project, ProjectNode, InstanceProjectNode}, project::{Project, ProjectNode, InstanceProjectNode},
message_queue::MessageQueue, message_queue::MessageQueue,
vfs::{Vfs, VfsItem}, imfs::{Imfs, ImfsItem},
}; };
pub struct RbxSession { pub struct RbxSession {
@@ -18,15 +18,15 @@ pub struct RbxSession {
paths_to_ids: HashMap<PathBuf, RbxId>, paths_to_ids: HashMap<PathBuf, RbxId>,
ids_to_project_paths: HashMap<RbxId, String>, ids_to_project_paths: HashMap<RbxId, String>,
message_queue: Arc<MessageQueue>, message_queue: Arc<MessageQueue>,
vfs: Arc<Mutex<Vfs>>, imfs: Arc<Mutex<Imfs>>,
project: Arc<Project>, project: Arc<Project>,
} }
impl RbxSession { impl RbxSession {
pub fn new(project: Arc<Project>, vfs: Arc<Mutex<Vfs>>, message_queue: Arc<MessageQueue>) -> RbxSession { pub fn new(project: Arc<Project>, imfs: Arc<Mutex<Imfs>>, message_queue: Arc<MessageQueue>) -> RbxSession {
let (tree, paths_to_ids, ids_to_project_paths) = { let (tree, paths_to_ids, ids_to_project_paths) = {
let temp_vfs = vfs.lock().unwrap(); let temp_imfs = imfs.lock().unwrap();
construct_initial_tree(&project, &temp_vfs) construct_initial_tree(&project, &temp_imfs)
}; };
RbxSession { RbxSession {
@@ -34,7 +34,7 @@ impl RbxSession {
paths_to_ids, paths_to_ids,
ids_to_project_paths, ids_to_project_paths,
message_queue, message_queue,
vfs, imfs,
project, project,
} }
} }
@@ -66,7 +66,7 @@ impl RbxSession {
fn construct_initial_tree( fn construct_initial_tree(
project: &Project, project: &Project,
vfs: &Vfs, imfs: &Imfs,
) -> (RbxTree, HashMap<PathBuf, RbxId>, HashMap<RbxId, String>) { ) -> (RbxTree, HashMap<PathBuf, RbxId>, HashMap<RbxId, String>) {
let paths_to_ids = HashMap::new(); let paths_to_ids = HashMap::new();
let ids_to_project_paths = HashMap::new(); let ids_to_project_paths = HashMap::new();
@@ -80,7 +80,7 @@ fn construct_initial_tree(
let mut context = ConstructContext { let mut context = ConstructContext {
tree, tree,
vfs, imfs,
paths_to_ids, paths_to_ids,
ids_to_project_paths, ids_to_project_paths,
}; };
@@ -98,7 +98,7 @@ fn construct_initial_tree(
struct ConstructContext<'a> { struct ConstructContext<'a> {
tree: RbxTree, tree: RbxTree,
vfs: &'a Vfs, imfs: &'a Imfs,
paths_to_ids: HashMap<PathBuf, RbxId>, paths_to_ids: HashMap<PathBuf, RbxId>,
ids_to_project_paths: HashMap<RbxId, String>, ids_to_project_paths: HashMap<RbxId, String>,
} }
@@ -151,8 +151,8 @@ fn construct_sync_point_node(
instance_name: &str, instance_name: &str,
file_path: &Path, file_path: &Path,
) -> RbxId { ) -> RbxId {
match context.vfs.get(&file_path) { match context.imfs.get(&file_path) {
Some(VfsItem::File(file)) => { Some(ImfsItem::File(file)) => {
let contents = str::from_utf8(&file.contents).unwrap(); let contents = str::from_utf8(&file.contents).unwrap();
let mut properties = HashMap::new(); let mut properties = HashMap::new();
@@ -169,7 +169,7 @@ fn construct_sync_point_node(
id id
}, },
Some(VfsItem::Directory(directory)) => { Some(ImfsItem::Directory(directory)) => {
let instance = RbxInstance { let instance = RbxInstance {
class_name: "Folder".to_string(), class_name: "Folder".to_string(),
name: instance_name.to_string(), name: instance_name.to_string(),

View File

@@ -6,7 +6,7 @@ use std::{
use crate::{ use crate::{
message_queue::MessageQueue, message_queue::MessageQueue,
project::{Project, ProjectNode}, project::{Project, ProjectNode},
vfs::Vfs, imfs::Imfs,
session_id::SessionId, session_id::SessionId,
rbx_session::RbxSession, rbx_session::RbxSession,
fs_watcher::FsWatcher, fs_watcher::FsWatcher,
@@ -20,15 +20,15 @@ pub struct Session {
fs_watcher: FsWatcher, fs_watcher: FsWatcher,
} }
fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<()> {
match project_node { match project_node {
ProjectNode::Instance(node) => { ProjectNode::Instance(node) => {
for child in node.children.values() { for child in node.children.values() {
add_sync_points(vfs, child)?; add_sync_points(imfs, child)?;
} }
}, },
ProjectNode::SyncPoint(node) => { ProjectNode::SyncPoint(node) => {
vfs.add_root(&node.path)?; imfs.add_root(&node.path)?;
}, },
} }
@@ -37,23 +37,23 @@ 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(); let mut imfs = Imfs::new();
add_sync_points(&mut vfs, &project.tree) add_sync_points(&mut imfs, &project.tree)
.expect("Could not add sync points when starting new Rojo session"); .expect("Could not add sync points when starting new Rojo session");
let vfs = Arc::new(Mutex::new(vfs)); let imfs = Arc::new(Mutex::new(imfs));
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 rbx_session = Arc::new(Mutex::new(RbxSession::new( let rbx_session = Arc::new(Mutex::new(RbxSession::new(
Arc::clone(&project), Arc::clone(&project),
Arc::clone(&vfs), Arc::clone(&imfs),
Arc::clone(&message_queue), Arc::clone(&message_queue),
))); )));
let fs_watcher = FsWatcher::start( let fs_watcher = FsWatcher::start(
Arc::clone(&vfs), Arc::clone(&imfs),
Arc::clone(&rbx_session), Arc::clone(&rbx_session),
); );

View File

@@ -22,7 +22,6 @@ fn foo() {
let project = Project::load_exact(&project_file_location).unwrap(); let project = Project::load_exact(&project_file_location).unwrap();
assert_eq!(project.name, "foo"); assert_eq!(project.name, "foo");
assert_eq!(project.tree.len(), 1);
} }
#[test] #[test]
@@ -31,5 +30,4 @@ fn empty() {
let project = Project::load_exact(&project_file_location).unwrap(); let project = Project::load_exact(&project_file_location).unwrap();
assert_eq!(project.name, "empty"); assert_eq!(project.name, "empty");
assert_eq!(project.tree.len(), 0);
} }

View File

@@ -1,6 +1,7 @@
{ {
"name": "foo", "name": "foo",
"tree": { "tree": {
"$className": "DataModel",
"ReplicatedStorage": { "ReplicatedStorage": {
"$className": "ReplicatedStorage", "$className": "ReplicatedStorage",
"Rojo": { "Rojo": {