diff --git a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__child_but_not.snap b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__child_but_not.snap new file mode 100644 index 000000000..c5b70248b --- /dev/null +++ b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__child_but_not.snap @@ -0,0 +1,14 @@ +--- +source: tests/rojo_test/syncback_util.rs +assertion_line: 48 +expression: "visualize_fs_snapshot(&fs_snapshot, &output_path)" +--- +added_files: + - "OnlyOneCopy\\child_of_one.luau" + - "ReplicatedStorage\\child_replicated_storage.luau" +added_dirs: + - OnlyOneCopy + - ReplicatedStorage +removed_files: [] +removed_dirs: [] + diff --git a/rojo-test/syncback-tests/child_but_not/expected/OnlyOneCopy/child_of_one.luau b/rojo-test/syncback-tests/child_but_not/expected/OnlyOneCopy/child_of_one.luau new file mode 100644 index 000000000..d23f92e7f --- /dev/null +++ b/rojo-test/syncback-tests/child_but_not/expected/OnlyOneCopy/child_of_one.luau @@ -0,0 +1 @@ +-- displace personality beam leadership occupy diff --git a/rojo-test/syncback-tests/child_but_not/expected/ReplicatedStorage/child_replicated_storage.luau b/rojo-test/syncback-tests/child_but_not/expected/ReplicatedStorage/child_replicated_storage.luau new file mode 100644 index 000000000..dc3e15bf4 --- /dev/null +++ b/rojo-test/syncback-tests/child_but_not/expected/ReplicatedStorage/child_replicated_storage.luau @@ -0,0 +1 @@ +-- skate bottle vain nonsense tablet diff --git a/rojo-test/syncback-tests/child_but_not/expected/default.project.json b/rojo-test/syncback-tests/child_but_not/expected/default.project.json new file mode 100644 index 000000000..d23f524c2 --- /dev/null +++ b/rojo-test/syncback-tests/child_but_not/expected/default.project.json @@ -0,0 +1,12 @@ +{ + "name": "child_but_not", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "$path": "ReplicatedStorage", + "OnlyOneCopy": { + "$path": "OnlyOneCopy" + } + } + } +} \ No newline at end of file diff --git a/rojo-test/syncback-tests/child_but_not/input.rbxl b/rojo-test/syncback-tests/child_but_not/input.rbxl new file mode 100644 index 000000000..9723a9142 Binary files /dev/null and b/rojo-test/syncback-tests/child_but_not/input.rbxl differ diff --git a/rojo-test/syncback-tests/child_but_not/output/default.project.json b/rojo-test/syncback-tests/child_but_not/output/default.project.json new file mode 100644 index 000000000..d23f524c2 --- /dev/null +++ b/rojo-test/syncback-tests/child_but_not/output/default.project.json @@ -0,0 +1,12 @@ +{ + "name": "child_but_not", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "$path": "ReplicatedStorage", + "OnlyOneCopy": { + "$path": "OnlyOneCopy" + } + } + } +} \ No newline at end of file diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 3ebfce618..e63ea5b4a 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -7,7 +7,7 @@ use anyhow::Context; use memofs::{DirEntry, IoResultExt, Vfs}; use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource}, syncback::{FsSnapshot, SyncbackReturn, SyncbackSnapshot}, }; @@ -173,6 +173,15 @@ pub fn syncback_dir_no_meta<'sync>( old_child.name() ); continue; + } else if matches!( + old_child.metadata().instigating_source, + Some(InstigatingSource::ProjectNode { .. }) + ) { + log::debug!( + "Skipping instance {} because it originates in a project file", + old_child.name() + ); + continue; } // This child exists in both doms. Pass it on. children.push(snapshot.with_joined_path(*new_child_ref, Some(old_child.id()))?); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index e86b5f430..52551cd5e 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -2,6 +2,7 @@ use std::path::Path; use anyhow::Context; use memofs::Vfs; +use rbx_xml::EncodeOptions; use crate::{ snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, @@ -18,7 +19,7 @@ pub fn snapshot_rbxmx( .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) - .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; + .with_context(|| format!("Malformed rbxmx file: {}", path.display()))?; let root_instance = temp_tree.root(); let children = root_instance.children(); @@ -49,11 +50,19 @@ pub fn syncback_rbxmx<'sync>( ) -> anyhow::Result> { let inst = snapshot.new_inst(); + let options = + EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); + // Long-term, we probably want to have some logic for if this contains a // script. That's a future endeavor though. let mut serialized = Vec::new(); - rbx_xml::to_writer_default(&mut serialized, snapshot.new_tree(), &[inst.referent()]) - .context("failed to serialize new rbxmx")?; + rbx_xml::to_writer( + &mut serialized, + snapshot.new_tree(), + &[inst.referent()], + options, + ) + .context("failed to serialize new rbxmx")?; Ok(SyncbackReturn { inst_snapshot: InstanceSnapshot::from_instance(inst), diff --git a/src/variant_eq.rs b/src/variant_eq.rs index 0db78a5e8..d99addc62 100644 --- a/src/variant_eq.rs +++ b/src/variant_eq.rs @@ -124,16 +124,16 @@ pub fn variant_eq(variant_a: &Variant, variant_b: &Variant) -> bool { } true } - (Variant::OptionalCFrame(a), Variant::OptionalCFrame(b)) => { - if let (Some(a2), Some(b2)) = (a, b) { - vector_eq(&a2.position, &b2.position) - && vector_eq(&a2.orientation.x, &b2.orientation.x) - && vector_eq(&a2.orientation.y, &b2.orientation.y) - && vector_eq(&a2.orientation.z, &b2.orientation.z) - } else { - false + (Variant::OptionalCFrame(a), Variant::OptionalCFrame(b)) => match (a, b) { + (Some(a), Some(b)) => { + vector_eq(&a.position, &b.position) + && vector_eq(&a.orientation.x, &b.orientation.x) + && vector_eq(&a.orientation.y, &b.orientation.y) + && vector_eq(&a.orientation.z, &b.orientation.z) } - } + (None, None) => true, + _ => false, + }, (Variant::PhysicalProperties(a), Variant::PhysicalProperties(b)) => match (a, b) { (PhysicalProperties::Default, PhysicalProperties::Default) => true, (PhysicalProperties::Custom(a2), PhysicalProperties::Custom(b2)) => { @@ -143,7 +143,7 @@ pub fn variant_eq(variant_a: &Variant, variant_b: &Variant) -> bool { && approx_eq!(f32, a2.elasticity_weight, b2.elasticity_weight) && approx_eq!(f32, a2.friction_weight, b2.friction_weight) } - (_, _) => false, + _ => false, }, (Variant::Ray(a), Variant::Ray(b)) => { vector_eq(&a.direction, &b.direction) && vector_eq(&a.origin, &b.origin) diff --git a/tests/tests/syncback.rs b/tests/tests/syncback.rs index b51562953..f351426e0 100644 --- a/tests/tests/syncback.rs +++ b/tests/tests/syncback.rs @@ -28,4 +28,5 @@ syncback_basic_test! { project_all_middleware, duplicate_rojo_id, string_value_project, + child_but_not, }