Stabilize asset registry publication order

This commit is contained in:
Rbanh 2026-07-13 11:46:51 -04:00
parent e1b2f86a49
commit cbd380a941
3 changed files with 647 additions and 602 deletions

File diff suppressed because it is too large Load Diff

View File

@ -215,6 +215,7 @@ fn sync_registry_from_browser(
next_records.push(record); next_records.push(record);
} }
sort_registry_records(&mut next_records);
let changed = previous_records != next_records; let changed = previous_records != next_records;
registry.records = next_records; registry.records = next_records;
if changed { if changed {
@ -234,6 +235,10 @@ fn imported_source_kind(kind_tag: &str) -> bool {
matches!(kind_tag, "Model" | "Texture" | "AudioClip") matches!(kind_tag, "Model" | "Texture" | "AudioClip")
} }
fn sort_registry_records(records: &mut [AssetRecord]) {
records.sort_by(|left, right| left.path.cmp(&right.path));
}
fn take_uniquely_moved_import_record( fn take_uniquely_moved_import_record(
existing: &mut HashMap<String, AssetRecord>, existing: &mut HashMap<String, AssetRecord>,
current_paths: &HashSet<String>, current_paths: &HashSet<String>,
@ -391,6 +396,44 @@ mod tests {
} }
} }
#[test]
fn registry_publication_order_is_stable_across_discovery_orders() {
let records = [
("assets/textures/z.png", "Texture"),
("assets/audio/a.ogg", "AudioClip"),
("assets/models/m.glb", "Model"),
]
.into_iter()
.map(|(path, kind_tag)| AssetRecord {
id: AssetId::new(),
path: path.into(),
label: path.into(),
kind_tag: kind_tag.into(),
source_fingerprint: None,
import_settings: ImportSettings::default(),
dependencies: Vec::new(),
})
.collect::<Vec<_>>();
let mut forward = records.clone();
let mut reverse = records.into_iter().rev().collect::<Vec<_>>();
sort_registry_records(&mut forward);
sort_registry_records(&mut reverse);
assert_eq!(forward, reverse);
assert_eq!(
forward
.iter()
.map(|record| record.path.as_str())
.collect::<Vec<_>>(),
[
"assets/audio/a.ogg",
"assets/models/m.glb",
"assets/textures/z.png",
]
);
}
#[test] #[test]
fn legacy_registry_record_loads_without_forcing_a_new_identity() { fn legacy_registry_record_loads_without_forcing_a_new_identity() {
let source = r#"( let source = r#"(

View File

@ -35,7 +35,9 @@ reimported.
Registry and generated-manifest writers parse the existing RON and compare the semantic value before Registry and generated-manifest writers parse the existing RON and compare the semantic value before
publication. Equivalent documents preserve their exact existing bytes, including layout and final publication. Equivalent documents preserve their exact existing bytes, including layout and final
newlines. Changed documents publish canonical pretty RON. newlines. Changed documents publish canonical pretty RON. Registry records are ordered by normalized
project path before comparison, so filesystem enumeration order cannot change their serialized
sequence on a fresh checkout.
Authoritative project validation remains read-only. It validates registry, animation, and Authoritative project validation remains read-only. It validates registry, animation, and
static-mesh fingerprints by length and digest, including same-size source edits. CI runs both static-mesh fingerprints by length and digest, including same-size source edits. CI runs both