From aeb2dd28096aa1875809d6046d5621be2862a740 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Mon, 10 Jun 2019 00:17:34 -0700 Subject: [PATCH 1/2] Support for .meta.json files other than init --- server/src/rbx_snapshot.rs | 68 +++++++++++++++---- .../meta_files/expected-snapshot.json | 42 +++++++++++- .../meta_files/src/DisableMe.meta.json | 6 ++ .../meta_files/src/DisableMe.server.lua | 0 .../meta_files/src/LocalizationTable.csv | 2 + .../src/LocalizationTable.meta.json | 5 ++ 6 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 test-projects/meta_files/src/DisableMe.meta.json create mode 100644 test-projects/meta_files/src/DisableMe.server.lua create mode 100644 test-projects/meta_files/src/LocalizationTable.csv create mode 100644 test-projects/meta_files/src/LocalizationTable.meta.json diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index c3e4fef9e..943abc1b2 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -295,7 +295,7 @@ fn snapshot_imfs_item<'source>( instance_name: Option>, ) -> SnapshotResult<'source> { match item { - ImfsItem::File(file) => snapshot_imfs_file(context, file, instance_name), + ImfsItem::File(file) => snapshot_imfs_file(context, imfs, file, instance_name), ImfsItem::Directory(directory) => snapshot_imfs_directory(context, imfs, directory, instance_name), } } @@ -345,18 +345,7 @@ fn snapshot_imfs_directory<'source>( path: file.path.to_path_buf(), })?; - if let Some(meta_class) = meta.class_name { - snapshot.class_name = Cow::Owned(meta_class); - } - - if let Some(meta_ignore_instances) = meta.ignore_unknown_instances { - snapshot.metadata.ignore_unknown_instances = meta_ignore_instances; - } - - for (key, value) in meta.properties { - let resolved_value = try_resolve_value(&snapshot.class_name, &key, &value)?; - snapshot.properties.insert(key, resolved_value); - } + meta.apply(&mut snapshot)?; } snapshot.metadata.source_path = Some(directory.path.to_owned()); @@ -393,8 +382,28 @@ struct InitMeta { properties: HashMap, } +impl InitMeta { + fn apply(self, snapshot: &mut RbxSnapshotInstance) -> Result<(), SnapshotError> { + if let Some(meta_class) = self.class_name { + snapshot.class_name = Cow::Owned(meta_class); + } + + if let Some(meta_ignore_instances) = self.ignore_unknown_instances { + snapshot.metadata.ignore_unknown_instances = meta_ignore_instances; + } + + for (key, value) in self.properties { + let resolved_value = try_resolve_value(&snapshot.class_name, &key, &value)?; + snapshot.properties.insert(key, resolved_value); + } + + Ok(()) + } +} + fn snapshot_imfs_file<'source>( context: &SnapshotContext, + imfs: &'source Imfs, file: &'source ImfsFile, instance_name: Option>, ) -> SnapshotResult<'source> { @@ -414,6 +423,11 @@ fn snapshot_imfs_file<'source>( if file_stem.ends_with(".model") { snapshot_json_model_file(file)? + } else if file_stem.ends_with(".meta") { + // Meta files are handled on a per-file basis + // None is *returned* instead of passed through + // so that it isn't treated as a mistake + return Ok(None); } else { None } @@ -421,11 +435,37 @@ fn snapshot_imfs_file<'source>( Some(_) | None => None, }; - if let Some(snapshot) = maybe_snapshot.as_mut() { + if let Some(mut snapshot) = maybe_snapshot.as_mut() { // Carefully preserve name from project manifest if present. if let Some(snapshot_name) = instance_name { snapshot.name = snapshot_name; } + + let meta_path = match extension { + Some("lua") => { + // Remove .server and .client + let file_path_str = file.path + .to_str().expect("Could not convert path to UTF-8"); + if let Some(name) = match_trailing(file_path_str, ".server.lua") { + PathBuf::from(name) + } else if let Some(name) = match_trailing(file_path_str, ".client.lua") { + PathBuf::from(name) + } else { + file.path.to_owned() + } + }, + + _ => file.path.to_owned(), + }.with_extension("meta.json"); + + if let Some(ImfsItem::File(meta_file)) = imfs.get(&meta_path) { + let meta: InitMeta = serde_json::from_slice(&meta_file.contents).map_err(|inner| SnapshotError::InitMetaError { + inner, + path: file.path.to_path_buf(), + })?; + + meta.apply(&mut snapshot)?; + } } else { info!("File generated no snapshot: {}", file.path.display()); } diff --git a/test-projects/meta_files/expected-snapshot.json b/test-projects/meta_files/expected-snapshot.json index 060c51092..ce8eb5623 100644 --- a/test-projects/meta_files/expected-snapshot.json +++ b/test-projects/meta_files/expected-snapshot.json @@ -20,16 +20,56 @@ } }, { - "name": "Script", + "name": "DisableMe", "class_name": "Script", "properties": { + "Source": { + "Type": "String", + "Value": "" + }, "Disabled": { "Type": "Bool", "Value": true + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": "src/DisableMe.server.lua", + "project_definition": null + } + }, + { + "name": "LocalizationTable", + "class_name": "LocalizationTable", + "properties": { + "SourceLocaleId": { + "Type": "String", + "Value": "es" }, + "Contents": { + "Type": "String", + "Value": "[{\"key\":\"Doge\",\"example\":\"A funny dog\",\"source\":\"Perro!\",\"values\":{\"en\":\"Doge!\"}}]" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/LocalizationTable.csv", + "project_definition": null + } + }, + { + "name": "Script", + "class_name": "Script", + "properties": { "Source": { "Type": "String", "Value": "print(\"Hello, world\")" + }, + "Disabled": { + "Type": "Bool", + "Value": true } }, "children": [], diff --git a/test-projects/meta_files/src/DisableMe.meta.json b/test-projects/meta_files/src/DisableMe.meta.json new file mode 100644 index 000000000..3ae03779a --- /dev/null +++ b/test-projects/meta_files/src/DisableMe.meta.json @@ -0,0 +1,6 @@ +{ + "ignoreUnknownInstances": true, + "properties": { + "Disabled": true + } +} \ No newline at end of file diff --git a/test-projects/meta_files/src/DisableMe.server.lua b/test-projects/meta_files/src/DisableMe.server.lua new file mode 100644 index 000000000..e69de29bb diff --git a/test-projects/meta_files/src/LocalizationTable.csv b/test-projects/meta_files/src/LocalizationTable.csv new file mode 100644 index 000000000..e5a90bbd0 --- /dev/null +++ b/test-projects/meta_files/src/LocalizationTable.csv @@ -0,0 +1,2 @@ +Key,Source,Context,Example,en +Doge,Perro!,,A funny dog,Doge! \ No newline at end of file diff --git a/test-projects/meta_files/src/LocalizationTable.meta.json b/test-projects/meta_files/src/LocalizationTable.meta.json new file mode 100644 index 000000000..3685ca81b --- /dev/null +++ b/test-projects/meta_files/src/LocalizationTable.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "SourceLocaleId": "es" + } +} \ No newline at end of file From 9065094f0abcdd7d5335537d50c3ca1e5f821a57 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Tue, 11 Jun 2019 20:29:27 -0700 Subject: [PATCH 2/2] Localize .meta.json application --- server/src/rbx_snapshot.rs | 97 ++++++++++--------- .../meta_files/expected-snapshot.json | 56 ++++++++--- .../meta_files/src/RobloxInstance.meta.json | 3 + .../meta_files/src/RobloxInstance.rbxmx | 11 +++ .../meta_files/src/StringValue.meta.json | 3 + test-projects/meta_files/src/StringValue.txt | 1 + 6 files changed, 111 insertions(+), 60 deletions(-) create mode 100644 test-projects/meta_files/src/RobloxInstance.meta.json create mode 100644 test-projects/meta_files/src/RobloxInstance.rbxmx create mode 100644 test-projects/meta_files/src/StringValue.meta.json create mode 100644 test-projects/meta_files/src/StringValue.txt diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 943abc1b2..5b280163f 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -39,7 +39,6 @@ use crate::{ const INIT_MODULE_NAME: &str = "init.lua"; const INIT_SERVER_NAME: &str = "init.server.lua"; const INIT_CLIENT_NAME: &str = "init.client.lua"; -const INIT_META_NAME: &str = "init.meta.json"; pub struct SnapshotContext { pub plugin_context: Option, @@ -309,7 +308,6 @@ fn snapshot_imfs_directory<'source>( let init_path = directory.path.join(INIT_MODULE_NAME); let init_server_path = directory.path.join(INIT_SERVER_NAME); let init_client_path = directory.path.join(INIT_CLIENT_NAME); - let init_meta_path = directory.path.join(INIT_META_NAME); let snapshot_name = instance_name .unwrap_or_else(|| { @@ -338,15 +336,7 @@ fn snapshot_imfs_directory<'source>( } }; - if let Some(ImfsItem::File(file)) = imfs.get(&init_meta_path) { - let meta: InitMeta = serde_json::from_slice(&file.contents) - .map_err(|inner| SnapshotError::InitMetaError { - inner, - path: file.path.to_path_buf(), - })?; - - meta.apply(&mut snapshot)?; - } + InitMeta::locate_and_apply(&mut snapshot, &imfs, &directory.path.join("init"))?; snapshot.metadata.source_path = Some(directory.path.to_owned()); @@ -399,6 +389,24 @@ impl InitMeta { Ok(()) } + + fn locate_and_apply( + snapshot: &mut RbxSnapshotInstance, + imfs: &Imfs, + path: &Path, + ) -> Result<(), SnapshotError> { + if let Some(ImfsItem::File(file)) = imfs.get(&path.with_extension("meta.json")) { + let meta: InitMeta = serde_json::from_slice(&file.contents) + .map_err(|inner| SnapshotError::InitMetaError { + inner, + path: file.path.to_path_buf(), + })?; + + meta.apply(snapshot)?; + } + + Ok(()) + } } fn snapshot_imfs_file<'source>( @@ -411,11 +419,11 @@ fn snapshot_imfs_file<'source>( .map(|v| v.to_str().expect("Could not convert extension to UTF-8")); let mut maybe_snapshot = match extension { - Some("lua") => snapshot_lua_file(file)?, - Some("csv") => snapshot_csv_file(file)?, - Some("txt") => snapshot_txt_file(file)?, - Some("rbxmx") => snapshot_xml_model_file(file)?, - Some("rbxm") => snapshot_binary_model_file(file)?, + Some("lua") => snapshot_lua_file(file, imfs)?, + Some("csv") => snapshot_csv_file(file, imfs)?, + Some("txt") => snapshot_txt_file(file, imfs)?, + Some("rbxmx") => snapshot_xml_model_file(file, imfs)?, + Some("rbxm") => snapshot_binary_model_file(file, imfs)?, Some("json") => { let file_stem = file.path .file_stem().expect("Could not extract file stem") @@ -440,32 +448,6 @@ fn snapshot_imfs_file<'source>( if let Some(snapshot_name) = instance_name { snapshot.name = snapshot_name; } - - let meta_path = match extension { - Some("lua") => { - // Remove .server and .client - let file_path_str = file.path - .to_str().expect("Could not convert path to UTF-8"); - if let Some(name) = match_trailing(file_path_str, ".server.lua") { - PathBuf::from(name) - } else if let Some(name) = match_trailing(file_path_str, ".client.lua") { - PathBuf::from(name) - } else { - file.path.to_owned() - } - }, - - _ => file.path.to_owned(), - }.with_extension("meta.json"); - - if let Some(ImfsItem::File(meta_file)) = imfs.get(&meta_path) { - let meta: InitMeta = serde_json::from_slice(&meta_file.contents).map_err(|inner| SnapshotError::InitMetaError { - inner, - path: file.path.to_path_buf(), - })?; - - meta.apply(&mut snapshot)?; - } } else { info!("File generated no snapshot: {}", file.path.display()); } @@ -489,6 +471,7 @@ fn snapshot_imfs_file<'source>( fn snapshot_lua_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let file_stem = file.path .file_stem().expect("Could not extract file stem") @@ -508,7 +491,7 @@ fn snapshot_lua_file<'source>( path: file.path.to_path_buf(), })?; - Ok(Some(RbxSnapshotInstance { + let mut snapshot = RbxSnapshotInstance { name: Cow::Borrowed(instance_name), class_name: Cow::Borrowed(class_name), properties: hashmap! { @@ -522,7 +505,11 @@ fn snapshot_lua_file<'source>( ignore_unknown_instances: false, project_definition: None, }, - })) + }; + + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path.with_file_name(instance_name))?; + + Ok(Some(snapshot)) } fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { @@ -536,6 +523,7 @@ fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { fn snapshot_txt_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let instance_name = file.path .file_stem().expect("Could not extract file stem") @@ -547,7 +535,7 @@ fn snapshot_txt_file<'source>( path: file.path.to_path_buf(), })?; - Ok(Some(RbxSnapshotInstance { + let mut snapshot = RbxSnapshotInstance { name: Cow::Borrowed(instance_name), class_name: Cow::Borrowed("StringValue"), properties: hashmap! { @@ -561,11 +549,16 @@ fn snapshot_txt_file<'source>( ignore_unknown_instances: false, project_definition: None, }, - })) + }; + + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + + Ok(Some(snapshot)) } fn snapshot_csv_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { /// Struct that holds any valid row from a Roblox CSV translation table. /// @@ -652,7 +645,7 @@ fn snapshot_csv_file<'source>( let table_contents = serde_json::to_string(&entries) .expect("Could not encode JSON for localization table"); - Ok(Some(RbxSnapshotInstance { + let mut snapshot = RbxSnapshotInstance { name: Cow::Borrowed(instance_name), class_name: Cow::Borrowed("LocalizationTable"), properties: hashmap! { @@ -666,7 +659,11 @@ fn snapshot_csv_file<'source>( ignore_unknown_instances: false, project_definition: None, }, - })) + }; + + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + + Ok(Some(snapshot)) } fn snapshot_json_model_file<'source>( @@ -730,6 +727,7 @@ impl JsonModelInstance { fn snapshot_xml_model_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let instance_name = file.path .file_stem().expect("Could not extract file stem") @@ -752,6 +750,7 @@ fn snapshot_xml_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), @@ -760,6 +759,7 @@ fn snapshot_xml_model_file<'source>( fn snapshot_binary_model_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let instance_name = file.path .file_stem().expect("Could not extract file stem") @@ -786,6 +786,7 @@ fn snapshot_binary_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), diff --git a/test-projects/meta_files/expected-snapshot.json b/test-projects/meta_files/expected-snapshot.json index ce8eb5623..f84244b92 100644 --- a/test-projects/meta_files/expected-snapshot.json +++ b/test-projects/meta_files/expected-snapshot.json @@ -23,13 +23,13 @@ "name": "DisableMe", "class_name": "Script", "properties": { - "Source": { - "Type": "String", - "Value": "" - }, "Disabled": { "Type": "Bool", "Value": true + }, + "Source": { + "Type": "String", + "Value": "" } }, "children": [], @@ -43,13 +43,13 @@ "name": "LocalizationTable", "class_name": "LocalizationTable", "properties": { - "SourceLocaleId": { - "Type": "String", - "Value": "es" - }, "Contents": { "Type": "String", "Value": "[{\"key\":\"Doge\",\"example\":\"A funny dog\",\"source\":\"Perro!\",\"values\":{\"en\":\"Doge!\"}}]" + }, + "SourceLocaleId": { + "Type": "String", + "Value": "es" } }, "children": [], @@ -59,17 +59,33 @@ "project_definition": null } }, + { + "name": "RobloxInstance", + "class_name": "Folder", + "properties": { + "Tags": { + "Type": "BinaryString", + "Value": "" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": null + } + }, { "name": "Script", "class_name": "Script", "properties": { - "Source": { - "Type": "String", - "Value": "print(\"Hello, world\")" - }, "Disabled": { "Type": "Bool", "Value": true + }, + "Source": { + "Type": "String", + "Value": "print(\"Hello, world\")" } }, "children": [], @@ -78,6 +94,22 @@ "source_path": "src/Script", "project_definition": null } + }, + { + "name": "StringValue", + "class_name": "StringValue", + "properties": { + "Value": { + "Type": "String", + "Value": "I'm supposed to put funny text here, aren't I? Oh well." + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": "src/StringValue.txt", + "project_definition": null + } } ], "metadata": { diff --git a/test-projects/meta_files/src/RobloxInstance.meta.json b/test-projects/meta_files/src/RobloxInstance.meta.json new file mode 100644 index 000000000..1025b06a5 --- /dev/null +++ b/test-projects/meta_files/src/RobloxInstance.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/test-projects/meta_files/src/RobloxInstance.rbxmx b/test-projects/meta_files/src/RobloxInstance.rbxmx new file mode 100644 index 000000000..f1b17e7c8 --- /dev/null +++ b/test-projects/meta_files/src/RobloxInstance.rbxmx @@ -0,0 +1,11 @@ + + true + null + nil + + + Folder + + + + \ No newline at end of file diff --git a/test-projects/meta_files/src/StringValue.meta.json b/test-projects/meta_files/src/StringValue.meta.json new file mode 100644 index 000000000..1025b06a5 --- /dev/null +++ b/test-projects/meta_files/src/StringValue.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/test-projects/meta_files/src/StringValue.txt b/test-projects/meta_files/src/StringValue.txt new file mode 100644 index 000000000..154159f91 --- /dev/null +++ b/test-projects/meta_files/src/StringValue.txt @@ -0,0 +1 @@ +I'm supposed to put funny text here, aren't I? Oh well. \ No newline at end of file