mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
Enhance model file conversion logic in ApiService
- Improved handling of .model.json5 files during conversion to init.meta.json5, ensuring compatibility by extracting only supported fields and warning about potential data loss from inline children. - Updated the script renaming process to derive base names from filesystem paths, preserving character encoding and improving consistency in metadata file naming. - Enhanced logging to provide clearer warnings and context during file operations, aiding in debugging and user awareness of changes.
This commit is contained in:
parent
e6944e3132
commit
dc1a912982
1 changed files with 90 additions and 6 deletions
|
|
@ -1026,13 +1026,84 @@ impl ApiService {
|
|||
.unwrap_or("");
|
||||
|
||||
if file_name.ends_with(".model.json5") || file_name.ends_with(".model.json") {
|
||||
// .model.json5 → init.meta.json5 with className and properties
|
||||
// Read the model file and rewrite as init.meta.json5
|
||||
// .model.json5 → init.meta.json5 with className and properties.
|
||||
// IMPORTANT: .model.json5 supports a "children" field for inline child
|
||||
// instances, but init.meta.json5 (DirectoryMetadata) does not. We must
|
||||
// parse the model and extract only the compatible fields, warning if
|
||||
// inline children would be lost.
|
||||
if standalone_path.exists() {
|
||||
let content = fs::read(standalone_path).unwrap_or_default();
|
||||
let raw = fs::read(standalone_path).unwrap_or_default();
|
||||
let init_meta_path = new_dir.join("init.meta.json5");
|
||||
|
||||
// Parse the model JSON to extract only meta-compatible fields
|
||||
let meta_content =
|
||||
if let Ok(model) = serde_json::from_slice::<serde_json::Value>(&raw) {
|
||||
// Warn about inline children that will be lost
|
||||
if let Some(children) = model.get("children").or(model.get("Children")) {
|
||||
if children.is_array()
|
||||
&& children.as_array().map_or(false, |a| !a.is_empty())
|
||||
{
|
||||
log::warn!(
|
||||
"Syncback: .model.json5 at {} contains inline children \
|
||||
that cannot be represented in init.meta.json5 — \
|
||||
these children will be lost during directory conversion",
|
||||
standalone_path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Build init.meta.json5 with only the supported fields
|
||||
let mut meta = serde_json::Map::new();
|
||||
if let Some(cn) = model
|
||||
.get("className")
|
||||
.or(model.get("ClassName"))
|
||||
.cloned()
|
||||
{
|
||||
meta.insert("className".to_string(), cn);
|
||||
}
|
||||
if let Some(props) = model
|
||||
.get("properties")
|
||||
.or(model.get("Properties"))
|
||||
.cloned()
|
||||
{
|
||||
if props.is_object()
|
||||
&& props.as_object().map_or(false, |o| !o.is_empty())
|
||||
{
|
||||
meta.insert("properties".to_string(), props);
|
||||
}
|
||||
}
|
||||
if let Some(attrs) = model
|
||||
.get("attributes")
|
||||
.or(model.get("Attributes"))
|
||||
.cloned()
|
||||
{
|
||||
if attrs.is_object()
|
||||
&& attrs.as_object().map_or(false, |o| !o.is_empty())
|
||||
{
|
||||
meta.insert("attributes".to_string(), attrs);
|
||||
}
|
||||
}
|
||||
if let Some(ignore) = model.get("ignoreUnknownInstances").cloned() {
|
||||
meta.insert("ignoreUnknownInstances".to_string(), ignore);
|
||||
}
|
||||
if let Some(id) = model.get("id").cloned() {
|
||||
meta.insert("id".to_string(), id);
|
||||
}
|
||||
|
||||
crate::json::to_vec_pretty_sorted(&serde_json::Value::Object(meta))
|
||||
.unwrap_or(raw.clone())
|
||||
} else {
|
||||
// Parse failed — copy raw as fallback (best-effort)
|
||||
log::warn!(
|
||||
"Syncback: Could not parse {} as JSON — \
|
||||
copying raw content to init.meta.json5",
|
||||
standalone_path.display()
|
||||
);
|
||||
raw
|
||||
};
|
||||
|
||||
self.suppress_path(&init_meta_path);
|
||||
fs::write(&init_meta_path, &content)
|
||||
fs::write(&init_meta_path, &meta_content)
|
||||
.with_context(|| format!("Failed to write {}", init_meta_path.display()))?;
|
||||
}
|
||||
} else if file_ext == "txt" {
|
||||
|
|
@ -2123,9 +2194,22 @@ impl ApiService {
|
|||
);
|
||||
} else if is_script {
|
||||
// Standalone script: write to adjacent Name.meta.json5
|
||||
// Derive the base name from the filesystem path (not instance.name())
|
||||
// to preserve Windows-invalid character encoding (e.g., %3F for ?).
|
||||
// This matches AdjacentMetadata::read_and_apply_all which uses file_stem().
|
||||
let parent_dir = inst_path.parent().context("No parent directory")?;
|
||||
let name = instance.name();
|
||||
let meta_path = parent_dir.join(format!("{}.meta.json5", name));
|
||||
let file_stem = inst_path
|
||||
.file_stem()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("");
|
||||
let base_name = file_stem
|
||||
.strip_suffix(".server")
|
||||
.or_else(|| file_stem.strip_suffix(".client"))
|
||||
.or_else(|| file_stem.strip_suffix(".plugin"))
|
||||
.or_else(|| file_stem.strip_suffix(".local"))
|
||||
.or_else(|| file_stem.strip_suffix(".legacy"))
|
||||
.unwrap_or(file_stem);
|
||||
let meta_path = parent_dir.join(format!("{}.meta.json5", base_name));
|
||||
|
||||
let meta = self.merge_or_build_meta(&meta_path, None, properties, attributes)?;
|
||||
let content = crate::json::to_vec_pretty_sorted(&meta)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue