mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-25 23:26:19 +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::{
|
use crate::{
|
||||||
snapshot::{InstanceMetadata, InstanceSnapshot},
|
snapshot::{InstanceMetadata, InstanceSnapshot},
|
||||||
vfs::{DirectorySnapshot, Vfs, VfsEntry, VfsFetcher, VfsSnapshot},
|
vfs::{DirectorySnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
context::InstanceSnapshotContext,
|
context::InstanceSnapshotContext,
|
||||||
error::SnapshotError,
|
error::SnapshotError,
|
||||||
|
meta_file::DirectoryMetadata,
|
||||||
middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware},
|
middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware},
|
||||||
snapshot_from_instance, snapshot_from_vfs,
|
snapshot_from_instance, snapshot_from_vfs,
|
||||||
};
|
};
|
||||||
@@ -44,7 +45,9 @@ impl SnapshotMiddleware for SnapshotDir {
|
|||||||
.ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?
|
.ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
Ok(Some(InstanceSnapshot {
|
let meta_path = entry.path().join("init.meta.json");
|
||||||
|
|
||||||
|
let mut snapshot = InstanceSnapshot {
|
||||||
snapshot_id: None,
|
snapshot_id: None,
|
||||||
metadata: InstanceMetadata {
|
metadata: InstanceMetadata {
|
||||||
instigating_source: Some(entry.path().to_path_buf().into()),
|
instigating_source: Some(entry.path().to_path_buf().into()),
|
||||||
@@ -55,7 +58,15 @@ impl SnapshotMiddleware for SnapshotDir {
|
|||||||
class_name: Cow::Borrowed("Folder"),
|
class_name: Cow::Borrowed("Folder"),
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
children: snapshot_children,
|
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 {
|
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(init_entry) = vfs.get(init_path).with_not_found()? {
|
||||||
if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_entry)? {
|
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 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.name = dir_snapshot.name;
|
||||||
init_snapshot.children = dir_snapshot.children;
|
init_snapshot.children = dir_snapshot.children;
|
||||||
// TODO: Metadata
|
// TODO: Apply metadata from folder
|
||||||
// TODO: Validate directory class name is "Folder"
|
|
||||||
|
|
||||||
return Ok(Some(init_snapshot));
|
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_dom_weak::UnresolvedRbxValue;
|
||||||
use rbx_reflection::try_resolve_value;
|
use rbx_reflection::try_resolve_value;
|
||||||
@@ -55,3 +55,65 @@ impl AdjacentMetadata {
|
|||||||
// TODO: Add method to allow selectively applying parts of metadata and
|
// TODO: Add method to allow selectively applying parts of metadata and
|
||||||
// throwing errors if invalid parts are specified.
|
// 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