diff --git a/plugin/src/Reconciler/diff.spec.lua b/plugin/src/Reconciler/diff.spec.lua index 6d62b8b7..163606c7 100644 --- a/plugin/src/Reconciler/diff.spec.lua +++ b/plugin/src/Reconciler/diff.spec.lua @@ -276,7 +276,7 @@ return function() end) describe("duplicate-named siblings", function() - it("should skip real DOM children with duplicate names", function() + it("should remove real DOM children with duplicate names when not in virtual DOM", function() local knownInstances = InstanceMap.new() local virtualInstances = { ROOT = { @@ -305,11 +305,11 @@ return function() assert(ok, tostring(patch)) - -- Duplicate-named children should be skipped (not removed) - assert(isEmpty(patch.removed)) + -- Duplicate-named children should be removed (matching handles pairing) + expect(#patch.removed).to.equal(2) end) - it("should skip virtual children with duplicate names among siblings", function() + it("should add virtual children with duplicate names among siblings", function() local knownInstances = InstanceMap.new() local virtualInstances = { ROOT = { @@ -340,8 +340,8 @@ return function() assert(ok, tostring(patch)) - -- Duplicate-named virtual children should not be added - assert(isEmpty(patch.added)) + -- Duplicate-named virtual children should be added (matching handles pairing) + expect(size(patch.added)).to.equal(2) end) end) diff --git a/plugin/src/Reconciler/diff.stress.spec.lua b/plugin/src/Reconciler/diff.stress.spec.lua index 14b0468d..453787d9 100644 --- a/plugin/src/Reconciler/diff.stress.spec.lua +++ b/plugin/src/Reconciler/diff.stress.spec.lua @@ -239,9 +239,8 @@ return function() local ok, patch = diff(instanceMap, virtualInstances, rootId) expect(ok).to.equal(true) - -- Duplicates should NOT be marked for removal - -- Only if they had unique names would they be candidates - expect(#patch.removed).to.equal(0) + -- Duplicates should be marked for removal (matching handles pairing) + expect(#patch.removed).to.equal(2) instanceMap:stop() end) @@ -290,9 +289,9 @@ return function() local ok, patch = diff(instanceMap, virtualInstances, rootId) expect(ok).to.equal(true) - -- Neither duplicate should be added since the path is ambiguous - expect(patch.added[dup1Id]).to.equal(nil) - expect(patch.added[dup2Id]).to.equal(nil) + -- Both duplicates should be added (matching handles pairing) + expect(patch.added[dup1Id]).to.be.ok() + expect(patch.added[dup2Id]).to.be.ok() instanceMap:stop() end) @@ -350,8 +349,8 @@ return function() local ok, patch = diff(instanceMap, virtualInstances, rootId) expect(ok).to.equal(true) - -- Grandchild should also NOT be added since its parent is ambiguous - expect(patch.added[grandchildId]).to.equal(nil) + -- Grandchild should be added along with its parent (matching handles pairing) + expect(patch.added[grandchildId]).to.be.ok() instanceMap:stop() end) diff --git a/plugin/src/Reconciler/hydrate.lua b/plugin/src/Reconciler/hydrate.lua index ac66682d..8be0319d 100644 --- a/plugin/src/Reconciler/hydrate.lua +++ b/plugin/src/Reconciler/hydrate.lua @@ -41,7 +41,7 @@ local function hydrate(instanceMap, virtualInstances, rootId, rootInstance) end -- Use the 3-pass matching algorithm to pair virtual ↔ studio children - local result = Matching.matchChildren(validVirtualIds, existingChildren, virtualInstances, instanceMap) + local result = Matching.matchChildren(validVirtualIds, existingChildren, virtualInstances) -- Recursively hydrate matched pairs for _, pair in result.matched do diff --git a/plugin/src/Reconciler/matching.lua b/plugin/src/Reconciler/matching.lua index 9e0f8abf..0e19fb95 100644 --- a/plugin/src/Reconciler/matching.lua +++ b/plugin/src/Reconciler/matching.lua @@ -114,8 +114,7 @@ local Matching = {} function Matching.matchChildren( virtualChildren: { string }, studioChildren: { Instance }, - virtualInstances: { [string]: any }, - instanceMap: any + virtualInstances: { [string]: any } ) local matched: { { virtualId: string, studioInstance: Instance } } = {} local remainingVirtual: { string } = table.clone(virtualChildren) @@ -344,7 +343,7 @@ function Matching._computeChangeCount( end -- Recursive: match children and sum costs - local childResult = Matching.matchChildren(validVChildren, studioKids, virtualInstances, nil) + local childResult = Matching.matchChildren(validVChildren, studioKids, virtualInstances) -- Matched children: recursively score each pair for _, pair in childResult.matched do diff --git a/rojo-test/serve-tests/ref_two_way_sync/src/Workspace/TestModel/init.meta.json5 b/rojo-test/serve-tests/ref_two_way_sync/src/Workspace/TestModel/init.meta.json5 index 1e894a97..233090f1 100644 --- a/rojo-test/serve-tests/ref_two_way_sync/src/Workspace/TestModel/init.meta.json5 +++ b/rojo-test/serve-tests/ref_two_way_sync/src/Workspace/TestModel/init.meta.json5 @@ -1,6 +1,6 @@ { "className": "Model", "attributes": { - "Rojo_Ref_PrimaryPart": "Workspace/TestModel/Part1" + "Rojo_Ref_PrimaryPart": "Workspace/TestModel/Part1.model.json5" } } diff --git a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__child_but_not-stdout.snap b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__child_but_not-stdout.snap index b1058161..46d80326 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__child_but_not-stdout.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__child_but_not-stdout.snap @@ -3,6 +3,8 @@ source: tests/rojo_test/syncback_util.rs expression: normalized_stdout --- Writing OnlyOneCopy/child_of_one.luau +Writing ReplicatedStorage/OnlyOneCopy/child_of_one.luau Writing ReplicatedStorage/child_replicated_storage.luau +Writing ReplicatedStorage/OnlyOneCopy Removing OnlyOneCopy/.gitkeep Removing ReplicatedStorage/.gitkeep diff --git a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__rbxm_fallback-stdout.snap b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__rbxm_fallback-stdout.snap index 7baf6c3e..6856e896 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__rbxm_fallback-stdout.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__rbxm_fallback-stdout.snap @@ -2,8 +2,12 @@ source: tests/rojo_test/syncback_util.rs expression: normalized_stdout --- +Writing src/ChildWithDuplicates/DuplicateChild/.gitkeep +Writing src/ChildWithDuplicates/DuplicateChild~1/init.meta.json5 Writing src/ChildWithoutDuplicates/Child/.gitkeep Writing src/ChildWithDuplicates +Writing src/ChildWithDuplicates/DuplicateChild +Writing src/ChildWithDuplicates/DuplicateChild~1 Writing src/ChildWithoutDuplicates Writing src/ChildWithoutDuplicates/Child Removing src/ChildWithDuplicates/.gitkeep diff --git a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__respect_old_middleware-stdout.snap b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__respect_old_middleware-stdout.snap index 532f88ab..c8ae87cd 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__respect_old_middleware-stdout.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__respect_old_middleware-stdout.snap @@ -4,5 +4,6 @@ expression: normalized_stdout --- Writing default.project.json5 Writing src/model_json.model.json5 +Writing src/project_node.model.json5 Writing src/rbxm.rbxm Writing src/rbxmx.rbxmx diff --git a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__duplicate_rojo_id-container.model.json5.snap b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__duplicate_rojo_id-container.model.json5.snap index 1aef5772..ef2c6d6b 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__duplicate_rojo_id-container.model.json5.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__duplicate_rojo_id-container.model.json5.snap @@ -7,7 +7,7 @@ expression: container.model.json5 { attributes: { Rojo_Id: "value_1", - Rojo_Ref_Value: "ReplicatedStorage/container/value_1" + Rojo_Ref_Value: "ReplicatedStorage/container/value_1.model.json5" }, className: "ObjectValue", name: "value_1" @@ -15,7 +15,7 @@ expression: container.model.json5 { attributes: { Rojo_Id: "value_1", - Rojo_Ref_Value: "ReplicatedStorage/container/value_2" + Rojo_Ref_Value: "ReplicatedStorage/container/value_2.model.json5" }, className: "ObjectValue", name: "value_2" diff --git a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_blank-src__pointer.model.json5.snap b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_blank-src__pointer.model.json5.snap index c2bd235f..0fe7fc11 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_blank-src__pointer.model.json5.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_blank-src__pointer.model.json5.snap @@ -4,7 +4,7 @@ expression: src/pointer.model.json5 --- { attributes: { - Rojo_Ref_Value: "ReplicatedStorage/target" + Rojo_Ref_Value: "ReplicatedStorage/target.txt" }, className: "ObjectValue" } diff --git a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer1.model.json5.snap b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer1.model.json5.snap index 79c8250c..3040e866 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer1.model.json5.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer1.model.json5.snap @@ -4,7 +4,7 @@ expression: src/Pointer1.model.json5 --- { attributes: { - Rojo_Ref_Value: "ReplicatedStorage/Target1" + Rojo_Ref_Value: "ReplicatedStorage/Target1.model.json5" }, className: "ObjectValue" } diff --git a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer2.model.json5.snap b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer2.model.json5.snap index 77fe2f05..9d512230 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer2.model.json5.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer2.model.json5.snap @@ -4,7 +4,7 @@ expression: src/Pointer2.model.json5 --- { attributes: { - Rojo_Ref_Value: "ReplicatedStorage/Target2" + Rojo_Ref_Value: "ReplicatedStorage/Target2.model.json5" }, className: "ObjectValue" } diff --git a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer3.model.json5.snap b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer3.model.json5.snap index 874c8b54..b0f55a59 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer3.model.json5.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__ref_properties_pruned-src__Pointer3.model.json5.snap @@ -4,7 +4,7 @@ expression: src/Pointer3.model.json5 --- { attributes: { - Rojo_Ref_Value: "ReplicatedStorage/Target3" + Rojo_Ref_Value: "ReplicatedStorage/Target3.model.json5" }, className: "ObjectValue" } diff --git a/src/change_processor.rs b/src/change_processor.rs index 24666859..796c2351 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -485,10 +485,8 @@ impl JobThreadContext { // this function is called. The index still stores old filesystem // paths. Remap them: replace the old directory segment with the // new one so we can find the actual files. - let old_segments = crate::split_ref_path(old_path); - let old_segment = old_segments.last().map(|s| s.as_str()).unwrap_or(old_path); - let new_segments = crate::split_ref_path(new_path); - let new_segment = new_segments.last().map(|s| s.as_str()).unwrap_or(new_path); + let old_segment = old_path.rsplit('/').next().unwrap_or(old_path); + let new_segment = new_path.rsplit('/').next().unwrap_or(new_path); // Pre-compute slugified forms for fallback comparison. let slugified_old = if name_needs_slugify(old_segment) { @@ -1202,11 +1200,17 @@ impl JobThreadContext { // Capture the old path BEFORE rename for Rojo_Ref_* path updates. // Must be computed before the `tree.get_instance(id)` borrow. - let old_ref_path = if update.changed_name.is_some() { - Some(crate::ref_target_path_from_tree(&tree, id)) - } else { - None - }; + let old_ref_path = + if update.changed_name.is_some() || update.changed_class_name.is_some() { + Some(crate::ref_target_path_from_tree(&tree, id)) + } else { + None + }; + + // The new filesystem name segment after a rename. Set during + // rename handling and used by the ref path update code to build + // the correct filesystem-name-based ref path. + let mut new_ref_segment: Option = None; if let Some(instance) = tree.get_instance(id) { // Track the current source file path — rename and ClassName @@ -1278,6 +1282,8 @@ impl JobThreadContext { // The init file moved with the directory. overridden_source_path = Some(new_dir_path.join(file_name)); + new_ref_segment = + Some(slugified_new_name.clone()); let old_meta = grandparent.join(format!( "{}.meta.json5", dir_name @@ -1438,6 +1444,8 @@ impl JobThreadContext { effective_meta_base = old_base; } else { overridden_source_path = Some(new_path.clone()); + new_ref_segment = + Some(new_file_name.clone()); let old_meta = parent .join(format!("{}.meta.json5", old_base)); let new_meta = parent.join(format!( @@ -1616,6 +1624,14 @@ impl JobThreadContext { ); } else { overridden_source_path = Some(new_path.clone()); + // For standalone files, the ref path + // segment changes with the extension. + // For init files, the directory name + // (ref segment) is unchanged. + if !is_init { + new_ref_segment = + Some(new_file_name.clone()); + } } } } else { @@ -1717,31 +1733,32 @@ impl JobThreadContext { // // NOTE: The tree name hasn't been updated yet (apply_patch_set // runs after this loop), so we can't use full_path_of for the - // new path. Construct it by replacing the last path segment. - // Use split_ref_path for escape-aware splitting (handles - // instance names containing "/"). + // new path. Construct it by replacing the last path segment + // with the NEW filesystem name (set during rename handling). if let Some(ref old_ref_path) = old_ref_path { - if let Some(ref new_name) = update.changed_name { - let segments = crate::split_ref_path(old_ref_path); + if let Some(ref segment) = new_ref_segment { + // Use the filesystem name computed during rename handling + let segments: Vec<&str> = old_ref_path.split('/').collect(); let new_ref_path = if segments.len() > 1 { - // Rebuild parent path from all segments except the last, - // re-escaping each segment to preserve the original format. - let parent_parts: Vec<_> = segments[..segments.len() - 1] - .iter() - .map(|s| crate::escape_ref_path_segment(s).into_owned()) - .collect(); - format!( - "{}/{}", - parent_parts.join("/"), - crate::escape_ref_path_segment(new_name) - ) + let parent = segments[..segments.len() - 1].join("/"); + format!("{}/{}", parent, segment) } else { - // Root-level instance (no parent in path) - crate::escape_ref_path_segment(new_name).into_owned() + segment.clone() }; if *old_ref_path != new_ref_path { self.update_ref_paths_after_rename(old_ref_path, &new_ref_path); } + } else if update.changed_name.is_some() + || update.changed_class_name.is_some() + { + // Rename or class change was requested but no filesystem + // rename happened (e.g., ProjectNode, init-file class + // change where directory name stays the same). No ref + // path update needed. + log::trace!( + "Skipping ref path update for {:?}: no filesystem rename", + id + ); } } } diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 0b5b0864..8966b635 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -10,7 +10,7 @@ use rbx_dom_weak::{ use crate::{multimap::MultiMap, RojoRef}; -use super::{InstanceMetadata, InstanceSnapshot}; +use super::{InstigatingSource, InstanceMetadata, InstanceSnapshot}; /// An expanded variant of rbx_dom_weak's `WeakDom` that tracks additional /// metadata per instance that's Rojo-specific. @@ -291,8 +291,19 @@ impl RojoTree { pub fn filesystem_name_for(&self, id: Ref) -> String { if let Some(meta) = self.metadata_map.get(&id) { if let Some(source) = &meta.instigating_source { - if let Some(name) = source.path().file_name().and_then(|f| f.to_str()) { - return name.to_string(); + match source { + InstigatingSource::Path(_) => { + if let Some(name) = source.path().file_name().and_then(|f| f.to_str()) { + return name.to_string(); + } + } + InstigatingSource::ProjectNode { .. } => { + // Project-sourced instance: use instance name, not the + // project file path (which would be e.g. "default.project.json5"). + if let Some(inst) = self.inner.get_by_ref(id) { + return inst.name.clone(); + } + } } } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 30570db4..22919405 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -628,6 +628,17 @@ pub fn syncback_project<'sync>( } } + // Project children with $path are expected in the old DOM (loaded + // from their own path) AND may also appear as filesystem children of + // the parent's scanned directory. Exclude them from duplicate + // detection so the project child loop below can match them. + let project_path_child_names: HashSet = node + .children + .iter() + .filter(|(_, child_node)| child_node.path.is_some()) + .map(|(name, _)| name.to_lowercase()) + .collect(); + let mut old_duplicate_names: HashSet = HashSet::new(); { let mut seen: HashSet = HashSet::new(); @@ -636,6 +647,9 @@ pub fn syncback_project<'sync>( .get_old_instance(*child_ref) .expect("all children of Instances should be in old DOM"); let lower = child.name().to_lowercase(); + if project_path_child_names.contains(&lower) { + continue; + } if !seen.insert(lower.clone()) { old_duplicate_names.insert(lower); } diff --git a/src/syncback/dedup_suffix.rs b/src/syncback/dedup_suffix.rs index 9b4b85a6..f5edfe25 100644 --- a/src/syncback/dedup_suffix.rs +++ b/src/syncback/dedup_suffix.rs @@ -58,11 +58,6 @@ pub fn parse_dedup_suffix(stem: &str) -> Option<(&str, u32)> { None } -/// Checks whether a filename stem has a dedup suffix. -pub fn has_dedup_suffix(stem: &str) -> bool { - parse_dedup_suffix(stem).is_some() -} - /// Builds a dedup'd filename from a base stem, optional suffix number, and /// extension. /// @@ -180,13 +175,6 @@ mod tests { assert_eq!(parse_dedup_suffix("My Script~1"), Some(("My Script", 1))); } - #[test] - fn has_suffix() { - assert!(has_dedup_suffix("Foo~1")); - assert!(!has_dedup_suffix("Foo")); - assert!(!has_dedup_suffix("Foo~abc")); - } - #[test] fn build_name_file() { assert_eq!( diff --git a/tests/tests/two_way_sync.rs b/tests/tests/two_way_sync.rs index 4142574e..c4f1f1c9 100644 --- a/tests/tests/two_way_sync.rs +++ b/tests/tests/two_way_sync.rs @@ -6127,7 +6127,7 @@ fn ref_set_primary_part() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); }); } @@ -6156,7 +6156,7 @@ fn ref_set_object_value() { let model_path = session .path() .join("src/Workspace/TestObjectValue.model.json5"); - poll_meta_has_ref_attr(&model_path, "Rojo_Ref_Value", "Workspace/TestModel/Part1"); + poll_meta_has_ref_attr(&model_path, "Rojo_Ref_Value", "Workspace/TestModel/Part1.model.json5"); }); } @@ -6190,7 +6190,7 @@ fn ref_set_primary_part_to_nil() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Now set PrimaryPart to nil @@ -6273,7 +6273,7 @@ fn ref_change_target() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Change PrimaryPart to Part2 @@ -6294,7 +6294,7 @@ fn ref_change_target() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part2", + "Workspace/TestModel/Part2.model.json5", ); }); } @@ -6324,7 +6324,7 @@ fn ref_set_nil_then_set_again() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); let mut props2 = UstrMap::default(); @@ -6359,7 +6359,7 @@ fn ref_set_nil_then_set_again() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); }); } @@ -6402,7 +6402,7 @@ fn ref_with_name_change() { assert_meta_has_ref_attr( &new_meta, "Rojo_Ref_PrimaryPart", - "Workspace/RenamedModel/Part1", + "Workspace/RenamedModel/Part1.model.json5", ); }); } @@ -6433,7 +6433,7 @@ fn ref_only_change_creates_meta() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); }); } @@ -6467,7 +6467,7 @@ fn ref_on_model_json5_instance() { let model_path = session .path() .join("src/Workspace/TestObjectValue.model.json5"); - poll_meta_has_ref_attr(&model_path, "Rojo_Ref_Value", "Workspace/TestModel/Part1"); + poll_meta_has_ref_attr(&model_path, "Rojo_Ref_Value", "Workspace/TestModel/Part1.model.json5"); }); } @@ -6498,7 +6498,7 @@ fn ref_existing_meta_preserved() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Verify existing content wasn't clobbered @@ -6571,7 +6571,7 @@ fn ref_mixed_valid_and_invalid() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); }); } @@ -6614,7 +6614,7 @@ fn ref_stale_path_after_target_rename() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Step 2: Rename Part1 to RenamedPart @@ -6637,7 +6637,7 @@ fn ref_stale_path_after_target_rename() { assert_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/RenamedPart", + "Workspace/TestModel/RenamedPart.model.json5", ); }); } @@ -6671,7 +6671,7 @@ fn ref_stale_path_after_parent_rename() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Step 2: Rename the MODEL (parent) from TestModel to RenamedModel @@ -6700,7 +6700,7 @@ fn ref_stale_path_after_parent_rename() { assert_meta_has_ref_attr( &new_meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/RenamedModel/Part1", + "Workspace/RenamedModel/Part1.model.json5", ); }); } @@ -6829,7 +6829,7 @@ fn ref_ambiguous_path_no_crash() { let meta_path = session .path() .join("src/Workspace/DupParent/init.meta.json5"); - poll_meta_has_ref_attr(&meta_path, "Rojo_Ref_PrimaryPart", "Workspace/Target"); + poll_meta_has_ref_attr(&meta_path, "Rojo_Ref_PrimaryPart", "Workspace/Target.model.json5"); }); } @@ -6926,7 +6926,7 @@ fn ref_startup_index_rename_updates_preexisting_attr() { assert_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Rename Part1 to IndexTestPart WITHOUT any prior /api/write for Refs. @@ -6951,7 +6951,7 @@ fn ref_startup_index_rename_updates_preexisting_attr() { assert_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/IndexTestPart", + "Workspace/TestModel/IndexTestPart.model.json5", ); }); } @@ -6987,10 +6987,10 @@ fn ref_partial_removal_preserves_remaining_index_entry() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Verify second ref is there too - assert_meta_has_ref_attr(&meta_path, "Rojo_Ref_Adornee", "Workspace/TestModel/Part2"); + assert_meta_has_ref_attr(&meta_path, "Rojo_Ref_Adornee", "Workspace/TestModel/Part2.model.json5"); // Step 2: Remove PrimaryPart (set to nil), keep Adornee let mut props2 = UstrMap::default(); @@ -7010,7 +7010,7 @@ fn ref_partial_removal_preserves_remaining_index_entry() { thread::sleep(Duration::from_millis(300)); assert_meta_no_ref_attr(&meta_path, "Rojo_Ref_PrimaryPart"); // Adornee should still be there - assert_meta_has_ref_attr(&meta_path, "Rojo_Ref_Adornee", "Workspace/TestModel/Part2"); + assert_meta_has_ref_attr(&meta_path, "Rojo_Ref_Adornee", "Workspace/TestModel/Part2.model.json5"); // Step 3: Rename Part2. The RefPathIndex should still have the entry // for Adornee (not overbroad-removed when PrimaryPart was deleted). @@ -7032,7 +7032,7 @@ fn ref_partial_removal_preserves_remaining_index_entry() { assert_meta_has_ref_attr( &meta_path, "Rojo_Ref_Adornee", - "Workspace/TestModel/RenamedPart2", + "Workspace/TestModel/RenamedPart2.model.json5", ); }); } @@ -7066,7 +7066,7 @@ fn ref_rename_to_slugified_name_updates_ref_paths() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Rename Model to a name with forbidden characters. @@ -7097,7 +7097,7 @@ fn ref_rename_to_slugified_name_updates_ref_paths() { assert_meta_has_ref_attr( &new_meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/Slug:Model/Part1", + "Workspace/Slug_Model/Part1.model.json5", ); }); } @@ -7145,7 +7145,7 @@ fn ref_on_standalone_script() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); // Verify the wrong path does NOT have the attribute @@ -7191,7 +7191,7 @@ fn ref_on_txt_file_instance() { poll_meta_has_ref_attr( &meta_path, "Rojo_Ref_PrimaryPart", - "Workspace/TestModel/Part1", + "Workspace/TestModel/Part1.model.json5", ); }); }