mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-20 20:55:50 +00:00
Add init.meta.json support, untested
This commit is contained in:
@@ -4,12 +4,13 @@ use rbx_dom_weak::{RbxId, RbxTree};
|
||||
|
||||
use crate::{
|
||||
snapshot::{InstanceMetadata, InstanceSnapshot},
|
||||
vfs::{DirectorySnapshot, Vfs, VfsEntry, VfsFetcher, VfsSnapshot},
|
||||
vfs::{DirectorySnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot},
|
||||
};
|
||||
|
||||
use super::{
|
||||
context::InstanceSnapshotContext,
|
||||
error::SnapshotError,
|
||||
meta_file::DirectoryMetadata,
|
||||
middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware},
|
||||
snapshot_from_instance, snapshot_from_vfs,
|
||||
};
|
||||
@@ -44,7 +45,9 @@ impl SnapshotMiddleware for SnapshotDir {
|
||||
.ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?
|
||||
.to_string();
|
||||
|
||||
Ok(Some(InstanceSnapshot {
|
||||
let meta_path = entry.path().join("init.meta.json");
|
||||
|
||||
let mut snapshot = InstanceSnapshot {
|
||||
snapshot_id: None,
|
||||
metadata: InstanceMetadata {
|
||||
instigating_source: Some(entry.path().to_path_buf().into()),
|
||||
@@ -55,7 +58,15 @@ impl SnapshotMiddleware for SnapshotDir {
|
||||
class_name: Cow::Borrowed("Folder"),
|
||||
properties: HashMap::new(),
|
||||
children: snapshot_children,
|
||||
}))
|
||||
};
|
||||
|
||||
if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? {
|
||||
let meta_contents = meta_entry.contents(vfs)?;
|
||||
let mut metadata = DirectoryMetadata::from_slice(&meta_contents);
|
||||
metadata.apply_all(&mut snapshot);
|
||||
}
|
||||
|
||||
Ok(Some(snapshot))
|
||||
}
|
||||
|
||||
fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult {
|
||||
|
||||
@@ -126,10 +126,17 @@ fn snapshot_init<F: VfsFetcher>(
|
||||
if let Some(init_entry) = vfs.get(init_path).with_not_found()? {
|
||||
if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_entry)? {
|
||||
if let Some(mut init_snapshot) = snapshot_lua_file(vfs, &init_entry)? {
|
||||
if dir_snapshot.class_name != "Folder" {
|
||||
panic!(
|
||||
"init.lua, init.server.lua, and init.client.lua can \
|
||||
only be used if the instance produced by the parent \
|
||||
directory would be a Folder."
|
||||
);
|
||||
}
|
||||
|
||||
init_snapshot.name = dir_snapshot.name;
|
||||
init_snapshot.children = dir_snapshot.children;
|
||||
// TODO: Metadata
|
||||
// TODO: Validate directory class name is "Folder"
|
||||
// TODO: Apply metadata from folder
|
||||
|
||||
return Ok(Some(init_snapshot));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use rbx_dom_weak::UnresolvedRbxValue;
|
||||
use rbx_reflection::try_resolve_value;
|
||||
@@ -55,3 +55,65 @@ impl AdjacentMetadata {
|
||||
// TODO: Add method to allow selectively applying parts of metadata and
|
||||
// throwing errors if invalid parts are specified.
|
||||
}
|
||||
|
||||
/// Represents metadata that affects the instance resulting from the containing
|
||||
/// folder.
|
||||
///
|
||||
/// This is always sourced from a file named init.meta.json.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DirectoryMetadata {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ignore_unknown_instances: Option<bool>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
|
||||
pub properties: HashMap<String, UnresolvedRbxValue>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub class_name: Option<String>,
|
||||
}
|
||||
|
||||
impl DirectoryMetadata {
|
||||
pub fn from_slice(slice: &[u8]) -> Self {
|
||||
serde_json::from_slice(slice)
|
||||
// TODO: Turn into error type
|
||||
.expect("init.meta.json file was malformed")
|
||||
}
|
||||
|
||||
pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) {
|
||||
self.apply_ignore_unknown_instances(snapshot);
|
||||
self.apply_class_name(snapshot);
|
||||
self.apply_properties(snapshot);
|
||||
}
|
||||
|
||||
fn apply_class_name(&mut self, snapshot: &mut InstanceSnapshot) {
|
||||
if let Some(class_name) = self.class_name.take() {
|
||||
if snapshot.class_name != "Folder" {
|
||||
// TODO: Turn into error type
|
||||
panic!("className in init.meta.json can only be specified if the affected directory would turn into a Folder instance.");
|
||||
}
|
||||
|
||||
snapshot.class_name = Cow::Owned(class_name);
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) {
|
||||
if let Some(ignore) = self.ignore_unknown_instances.take() {
|
||||
snapshot.metadata.ignore_unknown_instances = ignore;
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) {
|
||||
let class_name = &snapshot.class_name;
|
||||
|
||||
let source_properties = self.properties.drain().map(|(key, value)| {
|
||||
try_resolve_value(class_name, &key, &value)
|
||||
.map(|resolved| (key, resolved))
|
||||
.expect("TODO: Handle rbx_reflection errors")
|
||||
});
|
||||
|
||||
for (key, value) in source_properties {
|
||||
snapshot.properties.insert(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user