diff --git a/server/src/imfs.rs b/server/src/imfs.rs index a1190a15..21f6be1e 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -105,6 +105,16 @@ impl Imfs { Ok(()) } + pub fn get_root_for_path<'a>(&'a self, path: &Path) -> Option<&'a Path> { + for root_path in &self.roots { + if path.starts_with(root_path) { + return Some(root_path); + } + } + + None + } + fn remove_item(&mut self, path: &Path) { if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) { for child_path in &directory.children { diff --git a/server/src/path_map.rs b/server/src/path_map.rs index f1907b30..ebb23364 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -1,5 +1,5 @@ use std::{ - path::{Path, PathBuf}, + path::{self, Path, PathBuf}, collections::{HashMap, HashSet}, }; @@ -70,4 +70,27 @@ impl PathMap { Some(root_value) } + + pub fn descend(&self, start_path: &Path, target_path: &Path) -> PathBuf { + let relative_path = target_path.strip_prefix(start_path) + .expect("target_path did not begin with start_path"); + let mut current_path = start_path.to_path_buf(); + + for component in relative_path.components() { + match component { + path::Component::Normal(name) => { + let next_path = current_path.join(name); + + if self.nodes.contains_key(&next_path) { + current_path = next_path; + } else { + return current_path; + } + }, + _ => unreachable!(), + } + } + + current_path + } } \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index ce93d6d7..0181267a 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -13,7 +13,7 @@ use crate::{ message_queue::{Message, MessageQueue}, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, - rbx_snapshot::{RbxSnapshotInstance, reify_root}, + rbx_snapshot::{RbxSnapshotInstance, reify_root, reconcile_subtree}, }; pub struct RbxSession { @@ -47,13 +47,16 @@ impl RbxSession { } fn path_created_or_updated(&mut self, path: &Path) { - if let Some(instance_id) = self.paths_to_node_ids.get(path) { - // TODO: Replace instance with ID `instance_id` with new instance - } + let imfs = self.imfs.lock().unwrap(); + let root_path = imfs.get_root_for_path(path) + .expect("Path was outside in-memory filesystem roots"); - // TODO: Crawl up path to find first node represented in the tree or a - // sync point root. That path immediately before we find an existing - // node should be read into the tree. + let closest_path = self.paths_to_node_ids.descend(root_path, path); + let &instance_id = self.paths_to_node_ids.get(&closest_path).unwrap(); + + let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) + .expect("Could not generate instance snapshot"); + reconcile_subtree(&mut self.tree, instance_id, &snapshot); } pub fn path_created(&mut self, path: &Path) { @@ -167,7 +170,7 @@ fn construct_instance_node<'a>( name: Cow::Borrowed(instance_name), properties: HashMap::new(), children, - update_trigger_paths: Vec::new(), + source_path: None, } } @@ -225,7 +228,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< class_name: Cow::Borrowed(class_name), properties, children: Vec::new(), - update_trigger_paths: vec![file.path.clone()], + source_path: Some(file.path.clone()), }) }, ImfsItem::Directory(directory) => { @@ -239,7 +242,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< name: Cow::Borrowed(""), // Assigned later in the method properties: HashMap::new(), children: Vec::new(), - update_trigger_paths: vec![directory.path.clone()], + source_path: Some(directory.path.clone()), } }; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index b8b3f32f..c7dd7b23 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -12,7 +12,7 @@ pub struct RbxSnapshotInstance<'a> { pub class_name: Cow<'a, str>, pub properties: HashMap, pub children: Vec>, - pub update_trigger_paths: Vec, + pub source_path: Option, } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance {