forked from rojo-rbx/rojo
Support nested partitions and partitions directly targeting services (#122)
* Do the nested partition thing * Tidy up touched code * Add nested partition test project, not fully functional * Clean up variable names, move path_metadata mutation strictly into snapshot_reconciler * Remove path_metadata, snapshotting is now pure * Factor out snapshot metadata storage to fix a missing case * Pull instance_name out of per_path_metadata, closer to what we need * Refactor to make metadata make more sense, part one * All appears to be well * Cull 'metadata_per_path' in favor of 'instances_per_path' * Remove SnapshotContext * InstanceMetadata -> PublicInstanceMetadata in web module * Build in snapshot testing system for testing... snapshots? * Remove pretty_assertions to see if it fixes a snapshot comparison bug * Reintroduce pretty assertions, it's not the cause of inequality * Fix snapshot tests with custom relative path serializer
This commit is contained in:
committed by
GitHub
parent
38e3c198f2
commit
ecb9b5e28f
@@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
collections::{HashSet, HashMap},
|
||||
path::{Path, PathBuf},
|
||||
str,
|
||||
sync::{Arc, Mutex},
|
||||
@@ -11,11 +11,11 @@ use log::{info, trace};
|
||||
use rbx_tree::{RbxTree, RbxId};
|
||||
|
||||
use crate::{
|
||||
project::Project,
|
||||
project::{Project, ProjectNode},
|
||||
message_queue::MessageQueue,
|
||||
imfs::{Imfs, ImfsItem},
|
||||
path_map::PathMap,
|
||||
rbx_snapshot::{SnapshotContext, snapshot_project_tree, snapshot_imfs_path},
|
||||
rbx_snapshot::{snapshot_project_tree, snapshot_project_node, snapshot_imfs_path},
|
||||
snapshot_reconciler::{InstanceChanges, reify_root, reconcile_subtree},
|
||||
};
|
||||
|
||||
@@ -23,24 +23,28 @@ const INIT_SCRIPT: &str = "init.lua";
|
||||
const INIT_SERVER_SCRIPT: &str = "init.server.lua";
|
||||
const INIT_CLIENT_SCRIPT: &str = "init.client.lua";
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct MetadataPerPath {
|
||||
pub instance_id: Option<RbxId>,
|
||||
pub instance_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
/// `source_path` or `project_definition` or both must both be Some.
|
||||
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
|
||||
pub struct MetadataPerInstance {
|
||||
pub source_path: Option<PathBuf>,
|
||||
pub ignore_unknown_instances: bool,
|
||||
|
||||
/// The path on the filesystem that the instance was read from the
|
||||
/// filesystem if it came from the filesystem.
|
||||
#[serde(serialize_with = "crate::path_serializer::serialize_option")]
|
||||
pub source_path: Option<PathBuf>,
|
||||
|
||||
/// Information about the instance that came from the project that defined
|
||||
/// it, if that's where it was defined.
|
||||
///
|
||||
/// A key-value pair where the key should be the name of the instance and
|
||||
/// the value is the ProjectNode from the instance's project.
|
||||
pub project_definition: Option<(String, ProjectNode)>,
|
||||
}
|
||||
|
||||
pub struct RbxSession {
|
||||
tree: RbxTree,
|
||||
|
||||
// TODO(#105): Change metadata_per_path to PathMap<Vec<MetadataPerPath>> for
|
||||
// path aliasing.
|
||||
metadata_per_path: PathMap<MetadataPerPath>,
|
||||
instances_per_path: PathMap<HashSet<RbxId>>,
|
||||
metadata_per_instance: HashMap<RbxId, MetadataPerInstance>,
|
||||
message_queue: Arc<MessageQueue<InstanceChanges>>,
|
||||
imfs: Arc<Mutex<Imfs>>,
|
||||
@@ -52,17 +56,17 @@ impl RbxSession {
|
||||
imfs: Arc<Mutex<Imfs>>,
|
||||
message_queue: Arc<MessageQueue<InstanceChanges>>,
|
||||
) -> RbxSession {
|
||||
let mut metadata_per_path = PathMap::new();
|
||||
let mut instances_per_path = PathMap::new();
|
||||
let mut metadata_per_instance = HashMap::new();
|
||||
|
||||
let tree = {
|
||||
let temp_imfs = imfs.lock().unwrap();
|
||||
reify_initial_tree(&project, &temp_imfs, &mut metadata_per_path, &mut metadata_per_instance)
|
||||
reify_initial_tree(&project, &temp_imfs, &mut instances_per_path, &mut metadata_per_instance)
|
||||
};
|
||||
|
||||
RbxSession {
|
||||
tree,
|
||||
metadata_per_path,
|
||||
instances_per_path,
|
||||
metadata_per_instance,
|
||||
message_queue,
|
||||
imfs,
|
||||
@@ -80,7 +84,7 @@ impl RbxSession {
|
||||
.expect("Path was outside in-memory filesystem roots");
|
||||
|
||||
// Find the closest instance in the tree that currently exists
|
||||
let mut path_to_snapshot = self.metadata_per_path.descend(root_path, path);
|
||||
let mut path_to_snapshot = self.instances_per_path.descend(root_path, path);
|
||||
|
||||
// If this is a file that might affect its parent if modified, we
|
||||
// should snapshot its parent instead.
|
||||
@@ -93,42 +97,44 @@ impl RbxSession {
|
||||
|
||||
trace!("Snapshotting path {}", path_to_snapshot.display());
|
||||
|
||||
let path_metadata = self.metadata_per_path.get(&path_to_snapshot).unwrap();
|
||||
let instances_at_path = self.instances_per_path.get(&path_to_snapshot)
|
||||
.expect("Metadata did not exist for path")
|
||||
.clone();
|
||||
|
||||
trace!("Metadata for path: {:?}", path_metadata);
|
||||
for instance_id in &instances_at_path {
|
||||
let instance_metadata = self.metadata_per_instance.get(&instance_id)
|
||||
.expect("Metadata for instance ID did not exist");
|
||||
|
||||
let instance_id = path_metadata.instance_id
|
||||
.expect("Instance did not exist in tree");
|
||||
let maybe_snapshot = match &instance_metadata.project_definition {
|
||||
Some((instance_name, project_node)) => {
|
||||
snapshot_project_node(&imfs, &project_node, Cow::Owned(instance_name.clone()))
|
||||
.unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display()))
|
||||
},
|
||||
None => {
|
||||
snapshot_imfs_path(&imfs, &path_to_snapshot, None)
|
||||
.unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display()))
|
||||
},
|
||||
};
|
||||
|
||||
// If this instance is a sync point, pull its name out of our
|
||||
// per-path metadata store.
|
||||
let instance_name = path_metadata.instance_name.as_ref()
|
||||
.map(|value| Cow::Owned(value.to_owned()));
|
||||
let snapshot = match maybe_snapshot {
|
||||
Some(snapshot) => snapshot,
|
||||
None => {
|
||||
trace!("Path resulted in no snapshot being generated.");
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
let mut context = SnapshotContext {
|
||||
metadata_per_path: &mut self.metadata_per_path,
|
||||
};
|
||||
let maybe_snapshot = snapshot_imfs_path(&imfs, &mut context, &path_to_snapshot, instance_name)
|
||||
.unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display()));
|
||||
trace!("Snapshot: {:#?}", snapshot);
|
||||
|
||||
let snapshot = match maybe_snapshot {
|
||||
Some(snapshot) => snapshot,
|
||||
None => {
|
||||
trace!("Path resulted in no snapshot being generated.");
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
trace!("Snapshot: {:#?}", snapshot);
|
||||
|
||||
reconcile_subtree(
|
||||
&mut self.tree,
|
||||
instance_id,
|
||||
&snapshot,
|
||||
&mut self.metadata_per_path,
|
||||
&mut self.metadata_per_instance,
|
||||
&mut changes,
|
||||
);
|
||||
reconcile_subtree(
|
||||
&mut self.tree,
|
||||
*instance_id,
|
||||
&snapshot,
|
||||
&mut self.instances_per_path,
|
||||
&mut self.metadata_per_instance,
|
||||
&mut changes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if changes.is_empty() {
|
||||
@@ -170,13 +176,13 @@ impl RbxSession {
|
||||
|
||||
pub fn path_removed(&mut self, path: &Path) {
|
||||
info!("Path removed: {}", path.display());
|
||||
self.metadata_per_path.remove(path);
|
||||
self.instances_per_path.remove(path);
|
||||
self.path_created_or_updated(path);
|
||||
}
|
||||
|
||||
pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) {
|
||||
info!("Path renamed from {} to {}", from_path.display(), to_path.display());
|
||||
self.metadata_per_path.remove(from_path);
|
||||
self.instances_per_path.remove(from_path);
|
||||
self.path_created_or_updated(from_path);
|
||||
self.path_created_or_updated(to_path);
|
||||
}
|
||||
@@ -188,33 +194,26 @@ impl RbxSession {
|
||||
pub fn get_instance_metadata(&self, id: RbxId) -> Option<&MetadataPerInstance> {
|
||||
self.metadata_per_instance.get(&id)
|
||||
}
|
||||
|
||||
pub fn debug_get_metadata_per_path(&self) -> &PathMap<MetadataPerPath> {
|
||||
&self.metadata_per_path
|
||||
}
|
||||
}
|
||||
|
||||
pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree {
|
||||
let mut metadata_per_path = PathMap::new();
|
||||
let mut instances_per_path = PathMap::new();
|
||||
let mut metadata_per_instance = HashMap::new();
|
||||
reify_initial_tree(project, imfs, &mut metadata_per_path, &mut metadata_per_instance)
|
||||
reify_initial_tree(project, imfs, &mut instances_per_path, &mut metadata_per_instance)
|
||||
}
|
||||
|
||||
fn reify_initial_tree(
|
||||
project: &Project,
|
||||
imfs: &Imfs,
|
||||
metadata_per_path: &mut PathMap<MetadataPerPath>,
|
||||
instances_per_path: &mut PathMap<HashSet<RbxId>>,
|
||||
metadata_per_instance: &mut HashMap<RbxId, MetadataPerInstance>,
|
||||
) -> RbxTree {
|
||||
let mut context = SnapshotContext {
|
||||
metadata_per_path,
|
||||
};
|
||||
let snapshot = snapshot_project_tree(imfs, &mut context, project)
|
||||
let snapshot = snapshot_project_tree(imfs, project)
|
||||
.expect("Could not snapshot project tree")
|
||||
.expect("Project did not produce any instances");
|
||||
|
||||
let mut changes = InstanceChanges::default();
|
||||
let tree = reify_root(&snapshot, metadata_per_path, metadata_per_instance, &mut changes);
|
||||
let tree = reify_root(&snapshot, instances_per_path, metadata_per_instance, &mut changes);
|
||||
|
||||
tree
|
||||
}
|
||||
Reference in New Issue
Block a user