diff --git a/server/Cargo.lock b/server/Cargo.lock index 26c6120d..9211b849 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -644,6 +644,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rbx-tree" version = "0.1.0" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#124175066fa31e114fe55cca627dad4cae571a63" dependencies = [ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -701,7 +702,7 @@ dependencies = [ "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)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx-tree 0.1.0", + "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1150,6 +1151,7 @@ dependencies = [ "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" +"checksum rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" diff --git a/server/Cargo.toml b/server/Cargo.toml index 9afa0d53..52036fef 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,7 +30,7 @@ regex = "1.0" lazy_static = "1.0" log = "0.4" env_logger = "0.5" -rbx-tree = { path = "../../rbx-tree" } +rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] diff --git a/server/src/project.rs b/server/src/project.rs index 5bec5112..78244856 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -142,7 +142,7 @@ pub enum ProjectNode { Regular { class_name: String, children: HashMap, - + // properties: HashMap, // ignore_unknown: bool, }, SyncPoint { diff --git a/server/src/session.rs b/server/src/session.rs index 3aef342f..ff1c3724 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -1,11 +1,15 @@ use std::{ collections::HashMap, sync::{Arc, RwLock, Mutex, mpsc}, + path::{Path, PathBuf}, thread, io, time::Duration, + str, }; +use serde_json; + use notify::{ self, DebouncedEvent, @@ -14,12 +18,12 @@ use notify::{ Watcher, }; -use rbx_tree::{RbxTree, RbxInstance}; +use rbx_tree::{RbxId, RbxTree, RbxInstance, RbxValue}; use crate::{ message_queue::MessageQueue, project::{Project, ProjectNode}, - vfs::Vfs, + vfs::{Vfs, VfsItem}, session_id::SessionId, }; @@ -30,6 +34,7 @@ pub struct Session { pub session_id: SessionId, pub message_queue: Arc, pub tree: Arc>, + paths_to_ids: HashMap, vfs: Arc>, watchers: Vec, } @@ -49,18 +54,104 @@ fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> Ok(()) } +fn read_sync_to_rbx( + tree: &mut RbxTree, + vfs: &Vfs, + paths_to_ids: &mut HashMap, + parent_node_id: RbxId, + project_node_name: &str, + path: &Path +) { + match vfs.get(path) { + Some(VfsItem::File(file)) => { + let contents = str::from_utf8(vfs.get_contents(&file.path).unwrap()).unwrap(); + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), RbxValue::String { value: contents.to_string() }); + + let instance = RbxInstance { + class_name: "ModuleScript".to_string(), + name: project_node_name.to_string(), + properties, + }; + + let id = tree.insert_instance(instance, parent_node_id); + paths_to_ids.insert(path.to_path_buf(), id); + }, + Some(VfsItem::Directory(directory)) => { + let instance = RbxInstance { + class_name: "Folder".to_string(), + name: project_node_name.to_string(), + properties: HashMap::new(), + }; + + let id = tree.insert_instance(instance, parent_node_id); + paths_to_ids.insert(path.to_path_buf(), id); + + for child_path in &directory.children { + let child_name = child_path.file_name().unwrap().to_str().unwrap(); + read_sync_to_rbx(tree, vfs, paths_to_ids, id, child_name, child_path); + } + }, + None => panic!("Couldn't read {} from disk", path.display()), + } +} + +fn read_to_rbx( + tree: &mut RbxTree, + vfs: &Vfs, + paths_to_ids: &mut HashMap, + parent_node_id: RbxId, + project_node_name: &str, + project_node: &ProjectNode +) { + match project_node { + ProjectNode::Regular { children, class_name, .. } => { + let instance = RbxInstance { + class_name: class_name.clone(), + name: project_node_name.to_string(), + properties: HashMap::new(), + }; + + let id = tree.insert_instance(instance, parent_node_id); + + for (child_name, child_project_node) in children { + read_to_rbx(tree, vfs, paths_to_ids, id, child_name, child_project_node); + } + }, + ProjectNode::SyncPoint { path } => { + read_sync_to_rbx(tree, vfs, paths_to_ids, parent_node_id, project_node_name, path); + }, + } +} + impl Session { pub fn new(project: Project) -> io::Result { - let session_id = SessionId::new(); - let vfs = Arc::new(Mutex::new(Vfs::new())); - let message_queue = Arc::new(MessageQueue::new()); + let mut vfs = Vfs::new(); + + let (change_tx, change_rx) = mpsc::channel(); + + add_sync_points(&mut vfs, &project.tree) + .expect("Could not add sync points when starting new Rojo session"); + + let mut tree = RbxTree::new(RbxInstance { + name: "ahhhh".to_string(), + class_name: "ahhh help me".to_string(), + properties: HashMap::new(), + }); + + let mut paths_to_ids = HashMap::new(); + + let root_id = tree.get_root_id(); + read_to_rbx(&mut tree, &vfs, &mut paths_to_ids, root_id, "root", &project.tree); + + println!("tree:\n{}", serde_json::to_string(&tree).unwrap()); + + let vfs = Arc::new(Mutex::new(vfs)); let mut watchers = Vec::new(); { - let mut vfs_temp = vfs.lock().unwrap(); - - add_sync_points(&mut vfs_temp, &project.tree) - .expect("Could not add sync points when starting new Rojo session"); + let vfs_temp = vfs.lock().unwrap(); for root in vfs_temp.get_roots() { let (watch_tx, watch_rx) = mpsc::channel(); @@ -72,6 +163,7 @@ impl Session { watchers.push(watcher); + let change_tx = change_tx.clone(); let vfs = Arc::clone(&vfs); thread::spawn(move || { @@ -82,15 +174,19 @@ impl Session { DebouncedEvent::Create(path) | DebouncedEvent::Write(path) => { let mut vfs = vfs.lock().unwrap(); vfs.add_or_update(&path).unwrap(); + change_tx.send(path.clone()).unwrap(); }, DebouncedEvent::Remove(path) => { let mut vfs = vfs.lock().unwrap(); vfs.remove(&path); + change_tx.send(path.clone()).unwrap(); }, DebouncedEvent::Rename(from_path, to_path) => { let mut vfs = vfs.lock().unwrap(); vfs.remove(&from_path); vfs.add_or_update(&to_path).unwrap(); + change_tx.send(from_path.clone()).unwrap(); + change_tx.send(to_path.clone()).unwrap(); }, _ => continue, }; @@ -103,14 +199,12 @@ impl Session { } } - let tree = RbxTree::new(RbxInstance { - name: "ahhhh".to_string(), - class_name: "ahhh help me".to_string(), - properties: HashMap::new(), - }); + let message_queue = Arc::new(MessageQueue::new()); + let session_id = SessionId::new(); Ok(Session { session_id, + paths_to_ids, project, message_queue, tree: Arc::new(RwLock::new(tree)), diff --git a/server/src/vfs.rs b/server/src/vfs.rs index 7ac6e0f4..d02e8290 100644 --- a/server/src/vfs.rs +++ b/server/src/vfs.rs @@ -33,13 +33,20 @@ impl Vfs { &self.roots } - pub fn get(&mut self, path: &Path) -> Option<&VfsItem> { + pub fn get(&self, path: &Path) -> Option<&VfsItem> { debug_assert!(path.is_absolute()); debug_assert!(self.is_valid_path(path)); self.items.get(path) } + pub fn get_contents(&self, path: &Path) -> Option<&[u8]> { + debug_assert!(path.is_absolute()); + debug_assert!(self.is_valid_path(path)); + + self.contents.get(path).map(Vec::as_slice) + } + pub fn remove(&mut self, path: &Path) { debug_assert!(path.is_absolute()); debug_assert!(self.is_valid_path(path)); @@ -82,13 +89,13 @@ impl Vfs { #[derive(Debug)] pub struct VfsFile { - path: PathBuf, + pub path: PathBuf, } #[derive(Debug)] pub struct VfsDirectory { - path: PathBuf, - children: HashSet, + pub path: PathBuf, + pub children: HashSet, } #[derive(Debug)] diff --git a/test-projects/single-sync-point/lib/main.lua b/test-projects/single-sync-point/lib/main.lua index e69de29b..36c9d9bc 100644 --- a/test-projects/single-sync-point/lib/main.lua +++ b/test-projects/single-sync-point/lib/main.lua @@ -0,0 +1 @@ +-- hello, from main \ No newline at end of file