Support .jsonc extension for all JSON files (#1159)

This commit is contained in:
Micah
2025-11-18 18:47:43 -08:00
committed by GitHub
parent 03410ced6d
commit ea70d89291
46 changed files with 759 additions and 153 deletions

View File

@@ -31,6 +31,10 @@ Making a new release? Simply add the new header with the version and date undern
## Unreleased ## Unreleased
* Added support for `.jsonc` files for all JSON-related files (e.g. `.project.jsonc` and `.meta.jsonc`) to accompany JSONC support ([#1159])
[#1159]: https://github.com/rojo-rbx/rojo/pull/1159
## [7.6.1] (November 6th, 2025) ## [7.6.1] (November 6th, 2025)
* Fixed a bug where the last sync timestamp was not updating correctly in the plugin ([#1132]) * Fixed a bug where the last sync timestamp was not updating correctly in the plugin ([#1132])

View File

@@ -13,7 +13,8 @@ use thiserror::Error;
use crate::{glob::Glob, json, resolution::UnresolvedValue, snapshot::SyncRule}; use crate::{glob::Glob, json, resolution::UnresolvedValue, snapshot::SyncRule};
static PROJECT_FILENAME: &str = "default.project.json"; /// Represents 'default' project names that act as `init` files
pub static DEFAULT_PROJECT_NAMES: [&str; 2] = ["default.project.json", "default.project.jsonc"];
/// Error type returned by any function that handles projects. /// Error type returned by any function that handles projects.
#[derive(Debug, Error)] #[derive(Debug, Error)]
@@ -131,7 +132,7 @@ impl Project {
pub fn is_project_file(path: &Path) -> bool { pub fn is_project_file(path: &Path) -> bool {
path.file_name() path.file_name()
.and_then(|name| name.to_str()) .and_then(|name| name.to_str())
.map(|name| name.ends_with(".project.json")) .map(|name| name.ends_with(".project.json") || name.ends_with(".project.jsonc"))
.unwrap_or(false) .unwrap_or(false)
} }
@@ -149,18 +150,19 @@ impl Project {
None None
} }
} else { } else {
let child_path = path.join(PROJECT_FILENAME); for filename in DEFAULT_PROJECT_NAMES {
let child_meta = fs::metadata(&child_path).ok()?; let child_path = path.join(filename);
let child_meta = fs::metadata(&child_path).ok()?;
if child_meta.is_file() { if child_meta.is_file() {
Some(child_path) return Some(child_path);
} else { }
// This is a folder with the same name as a Rojo default project
// file.
//
// That's pretty weird, but we can roll with it.
None
} }
// This is a folder with the same name as a Rojo default project
// file.
//
// That's pretty weird, but we can roll with it.
None
} }
} }
@@ -181,16 +183,20 @@ impl Project {
// If you're editing this to be generic, make sure you also alter the // If you're editing this to be generic, make sure you also alter the
// snapshot middleware to support generic init paths. // snapshot middleware to support generic init paths.
if file_name == PROJECT_FILENAME { for default_file_name in DEFAULT_PROJECT_NAMES {
let folder_name = self.folder_location().file_name().and_then(OsStr::to_str); if file_name == default_file_name {
if let Some(folder_name) = folder_name { let folder_name = self.folder_location().file_name().and_then(OsStr::to_str);
self.name = Some(folder_name.to_string()); if let Some(folder_name) = folder_name {
} else { self.name = Some(folder_name.to_string());
return Err(Error::FolderNameInvalid { return Ok(());
path: self.file_location.clone(), } else {
}); return Err(Error::FolderNameInvalid {
path: self.file_location.clone(),
});
}
} }
} else if let Some(fallback) = fallback { }
if let Some(fallback) = fallback {
self.name = Some(fallback.to_string()); self.name = Some(fallback.to_string());
} else { } else {
// As of the time of writing (July 10, 2024) there is no way for // As of the time of writing (July 10, 2024) there is no way for
@@ -257,6 +263,10 @@ impl Project {
project_file_location: &Path, project_file_location: &Path,
fallback_name: Option<&str>, fallback_name: Option<&str>,
) -> Result<Self, ProjectError> { ) -> Result<Self, ProjectError> {
log::debug!(
"Loading project file from {}",
project_file_location.display()
);
let project_path = project_file_location.to_path_buf(); let project_path = project_file_location.to_path_buf();
let contents = vfs.read(&project_path).map_err(|e| match e.kind() { let contents = vfs.read(&project_path).map_err(|e| match e.kind() {
io::ErrorKind::NotFound => Error::NoProjectFound { io::ErrorKind::NotFound => Error::NoProjectFound {
@@ -272,6 +282,24 @@ impl Project {
)?) )?)
} }
pub(crate) fn load_initial_project(vfs: &Vfs, path: &Path) -> Result<Self, ProjectError> {
if Self::is_project_file(path) {
Self::load_exact(vfs, path, None)
} else {
// Check for default projects.
for default_project_name in DEFAULT_PROJECT_NAMES {
let project_path = path.join(default_project_name);
if project_path.exists() {
return Self::load_exact(vfs, &project_path, None);
}
}
Err(Error::NoProjectFound {
path: path.to_path_buf(),
}
.into())
}
}
/// Checks if there are any compatibility issues with this project file and /// Checks if there are any compatibility issues with this project file and
/// warns the user if there are any. /// warns the user if there are any.
fn check_compatibility(&self) { fn check_compatibility(&self) {
@@ -530,7 +558,7 @@ mod test {
let project = Project::load_from_slice( let project = Project::load_from_slice(
project_json.as_bytes(), project_json.as_bytes(),
PathBuf::from("/test/default.project.json"), PathBuf::from("/test/default.project.jsonc"),
None, None,
) )
.expect("Failed to parse project with JSONC features"); .expect("Failed to parse project with JSONC features");

View File

@@ -1,5 +1,4 @@
use std::{ use std::{
borrow::Cow,
collections::HashSet, collections::HashSet,
io, io,
net::IpAddr, net::IpAddr,
@@ -101,15 +100,7 @@ impl ServeSession {
log::trace!("Starting new ServeSession at path {}", start_path.display()); log::trace!("Starting new ServeSession at path {}", start_path.display());
let project_path = if Project::is_project_file(start_path) { let root_project = Project::load_initial_project(&vfs, start_path)?;
Cow::Borrowed(start_path)
} else {
Cow::Owned(start_path.join("default.project.json"))
};
log::debug!("Loading project file from {}", project_path.display());
let root_project = Project::load_exact(&vfs, &project_path, None)?;
let mut tree = RojoTree::new(InstanceSnapshot::new()); let mut tree = RojoTree::new(InstanceSnapshot::new());

View File

@@ -1,24 +1,23 @@
use std::{collections::BTreeMap, path::Path}; use std::{collections::BTreeMap, path::Path};
use anyhow::Context; use anyhow::Context;
use memofs::{IoResultExt, Vfs}; use memofs::Vfs;
use rbx_dom_weak::ustr; use rbx_dom_weak::ustr;
use serde::Serialize; use serde::Serialize;
use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use crate::{
snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot},
use super::{ snapshot_middleware::meta_file::DirectoryMetadata,
dir::{dir_meta, snapshot_dir_no_meta},
meta_file::AdjacentMetadata,
}; };
use super::{dir::snapshot_dir_no_meta, meta_file::AdjacentMetadata};
pub fn snapshot_csv( pub fn snapshot_csv(
_context: &InstanceContext, _context: &InstanceContext,
vfs: &Vfs, vfs: &Vfs,
path: &Path, path: &Path,
name: &str, name: &str,
) -> anyhow::Result<Option<InstanceSnapshot>> { ) -> anyhow::Result<Option<InstanceSnapshot>> {
let meta_path = path.with_file_name(format!("{}.meta.json", name));
let contents = vfs.read(path)?; let contents = vfs.read(path)?;
let table_contents = convert_localization_csv(&contents).with_context(|| { let table_contents = convert_localization_csv(&contents).with_context(|| {
@@ -35,13 +34,10 @@ pub fn snapshot_csv(
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()
.instigating_source(path) .instigating_source(path)
.relevant_paths(vec![path.to_path_buf(), meta_path.clone()]), .relevant_paths(vec![path.to_path_buf()]),
); );
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { AdjacentMetadata::read_and_apply_all(vfs, path, name, &mut snapshot)?;
let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?;
metadata.apply_all(&mut snapshot)?;
}
Ok(Some(snapshot)) Ok(Some(snapshot))
} }
@@ -75,9 +71,7 @@ pub fn snapshot_csv_init(
init_snapshot.children = dir_snapshot.children; init_snapshot.children = dir_snapshot.children;
init_snapshot.metadata = dir_snapshot.metadata; init_snapshot.metadata = dir_snapshot.metadata;
if let Some(mut meta) = dir_meta(vfs, folder_path)? { DirectoryMetadata::read_and_apply_all(vfs, folder_path, &mut init_snapshot)?;
meta.apply_all(&mut init_snapshot)?;
}
Ok(Some(init_snapshot)) Ok(Some(init_snapshot))
} }
@@ -223,4 +217,72 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#,
insta::assert_yaml_snapshot!(instance_snapshot); insta::assert_yaml_snapshot!(instance_snapshot);
} }
#[test]
fn csv_init() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/root",
VfsSnapshot::dir([(
"init.csv",
VfsSnapshot::file(
r#"
Key,Source,Context,Example,es
Ack,Ack!,,An exclamation of despair,¡Ay!"#,
),
)]),
)
.unwrap();
let vfs = Vfs::new(imfs);
let instance_snapshot = snapshot_csv_init(
&InstanceContext::with_emit_legacy_scripts(Some(true)),
&vfs,
Path::new("/root/init.csv"),
)
.unwrap()
.unwrap();
insta::with_settings!({ sort_maps => true }, {
insta::assert_yaml_snapshot!(instance_snapshot);
});
}
#[test]
fn csv_init_with_meta() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/root",
VfsSnapshot::dir([
(
"init.csv",
VfsSnapshot::file(
r#"
Key,Source,Context,Example,es
Ack,Ack!,,An exclamation of despair,¡Ay!"#,
),
),
(
"init.meta.json",
VfsSnapshot::file(r#"{"id": "manually specified"}"#),
),
]),
)
.unwrap();
let vfs = Vfs::new(imfs);
let instance_snapshot = snapshot_csv_init(
&InstanceContext::with_emit_legacy_scripts(Some(true)),
&vfs,
Path::new("/root/init.csv"),
)
.unwrap()
.unwrap();
insta::with_settings!({ sort_maps => true }, {
insta::assert_yaml_snapshot!(instance_snapshot);
});
}
} }

View File

@@ -1,6 +1,6 @@
use std::path::Path; use std::path::Path;
use memofs::{DirEntry, IoResultExt, Vfs}; use memofs::{DirEntry, Vfs};
use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot};
@@ -16,26 +16,11 @@ pub fn snapshot_dir(
None => return Ok(None), None => return Ok(None),
}; };
if let Some(mut meta) = dir_meta(vfs, path)? { DirectoryMetadata::read_and_apply_all(vfs, path, &mut snapshot)?;
meta.apply_all(&mut snapshot)?;
}
Ok(Some(snapshot)) Ok(Some(snapshot))
} }
/// Retrieves the meta file that should be applied for this directory, if it
/// exists.
pub fn dir_meta(vfs: &Vfs, path: &Path) -> anyhow::Result<Option<DirectoryMetadata>> {
let meta_path = path.join("init.meta.json");
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? {
let metadata = DirectoryMetadata::from_slice(&meta_contents, meta_path)?;
Ok(Some(metadata))
} else {
Ok(None)
}
}
/// Snapshot a directory without applying meta files; useful for if the /// Snapshot a directory without applying meta files; useful for if the
/// directory's ClassName will change before metadata should be applied. For /// directory's ClassName will change before metadata should be applied. For
/// example, this can happen if the directory contains an `init.client.lua` /// example, this can happen if the directory contains an `init.client.lua`
@@ -73,11 +58,8 @@ pub fn snapshot_dir_no_meta(
.ok_or_else(|| anyhow::anyhow!("File name was not valid UTF-8: {}", path.display()))? .ok_or_else(|| anyhow::anyhow!("File name was not valid UTF-8: {}", path.display()))?
.to_string(); .to_string();
let meta_path = path.join("init.meta.json");
let relevant_paths = vec![ let relevant_paths = vec![
path.to_path_buf(), path.to_path_buf(),
meta_path,
// TODO: We shouldn't need to know about Lua existing in this // TODO: We shouldn't need to know about Lua existing in this
// middleware. Should we figure out a way for that function to add // middleware. Should we figure out a way for that function to add
// relevant paths to this middleware? // relevant paths to this middleware?

View File

@@ -1,6 +1,6 @@
use std::path::Path; use std::path::Path;
use memofs::{IoResultExt, Vfs}; use memofs::Vfs;
use rbx_dom_weak::ustr; use rbx_dom_weak::ustr;
use crate::{ use crate::{
@@ -25,8 +25,6 @@ pub fn snapshot_json(
let as_lua = json_to_lua(value).to_string(); let as_lua = json_to_lua(value).to_string();
let meta_path = path.with_file_name(format!("{}.meta.json", name));
let mut snapshot = InstanceSnapshot::new() let mut snapshot = InstanceSnapshot::new()
.name(name) .name(name)
.class_name("ModuleScript") .class_name("ModuleScript")
@@ -34,14 +32,11 @@ pub fn snapshot_json(
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()
.instigating_source(path) .instigating_source(path)
.relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) .relevant_paths(vec![path.to_path_buf()])
.context(context), .context(context),
); );
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { AdjacentMetadata::read_and_apply_all(vfs, path, name, &mut snapshot)?;
let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?;
metadata.apply_all(&mut snapshot)?;
}
Ok(Some(snapshot)) Ok(Some(snapshot))
} }
@@ -111,4 +106,42 @@ mod test {
insta::assert_yaml_snapshot!(instance_snapshot); insta::assert_yaml_snapshot!(instance_snapshot);
} }
#[test]
fn with_metadata() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/foo.json",
VfsSnapshot::file(
r#"{
"array": [1, 2, 3],
"int": 1234,
"float": 1234.5452,
}"#,
),
)
.unwrap();
imfs.load_snapshot(
"/foo.meta.json",
VfsSnapshot::file(
r#"{
"id": "manually specified"
}"#,
),
)
.unwrap();
let vfs = Vfs::new(imfs.clone());
let instance_snapshot = snapshot_json(
&InstanceContext::default(),
&vfs,
Path::new("/foo.json"),
"foo",
)
.unwrap()
.unwrap();
insta::assert_yaml_snapshot!(instance_snapshot);
}
} }

View File

@@ -1,14 +1,11 @@
use std::{path::Path, str}; use std::{path::Path, str};
use memofs::{IoResultExt, Vfs}; use memofs::Vfs;
use rbx_dom_weak::{types::Enum, ustr, HashMapExt as _, UstrMap}; use rbx_dom_weak::{types::Enum, ustr, HashMapExt as _, UstrMap};
use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot};
use super::{ use super::{dir::snapshot_dir_no_meta, meta_file::AdjacentMetadata, meta_file::DirectoryMetadata};
dir::{dir_meta, snapshot_dir_no_meta},
meta_file::AdjacentMetadata,
};
#[derive(Debug)] #[derive(Debug)]
pub enum ScriptType { pub enum ScriptType {
@@ -73,8 +70,6 @@ pub fn snapshot_lua(
); );
} }
let meta_path = path.with_file_name(format!("{}.meta.json", name));
let mut snapshot = InstanceSnapshot::new() let mut snapshot = InstanceSnapshot::new()
.name(name) .name(name)
.class_name(class_name) .class_name(class_name)
@@ -82,14 +77,11 @@ pub fn snapshot_lua(
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()
.instigating_source(path) .instigating_source(path)
.relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) .relevant_paths(vec![path.to_path_buf()])
.context(context), .context(context),
); );
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { AdjacentMetadata::read_and_apply_all(vfs, path, name, &mut snapshot)?;
let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?;
metadata.apply_all(&mut snapshot)?;
}
Ok(Some(snapshot)) Ok(Some(snapshot))
} }
@@ -126,9 +118,7 @@ pub fn snapshot_lua_init(
init_snapshot.children = dir_snapshot.children; init_snapshot.children = dir_snapshot.children;
init_snapshot.metadata = dir_snapshot.metadata; init_snapshot.metadata = dir_snapshot.metadata;
if let Some(mut meta) = dir_meta(vfs, folder_path)? { DirectoryMetadata::read_and_apply_all(vfs, folder_path, &mut init_snapshot)?;
meta.apply_all(&mut init_snapshot)?;
}
Ok(Some(init_snapshot)) Ok(Some(init_snapshot))
} }
@@ -300,7 +290,6 @@ mod test {
}); });
} }
#[ignore = "init.lua functionality has moved to the root snapshot function"]
#[test] #[test]
fn init_module_from_vfs() { fn init_module_from_vfs() {
let mut imfs = InMemoryFs::new(); let mut imfs = InMemoryFs::new();
@@ -312,11 +301,41 @@ mod test {
let vfs = Vfs::new(imfs); let vfs = Vfs::new(imfs);
let instance_snapshot = snapshot_lua( let instance_snapshot = snapshot_lua_init(
&InstanceContext::with_emit_legacy_scripts(Some(true)), &InstanceContext::with_emit_legacy_scripts(Some(true)),
&vfs, &vfs,
Path::new("/root"), Path::new("/root/init.lua"),
"root", ScriptType::Module,
)
.unwrap()
.unwrap();
insta::with_settings!({ sort_maps => true }, {
insta::assert_yaml_snapshot!(instance_snapshot);
});
}
#[test]
fn init_module_from_vfs_with_meta() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/root",
VfsSnapshot::dir([
("init.lua", VfsSnapshot::file("Hello!")),
(
"init.meta.json",
VfsSnapshot::file(r#"{"id": "manually specified"}"#),
),
]),
)
.unwrap();
let vfs = Vfs::new(imfs);
let instance_snapshot = snapshot_lua_init(
&InstanceContext::with_emit_legacy_scripts(Some(true)),
&vfs,
Path::new("/root/init.lua"),
ScriptType::Module, ScriptType::Module,
) )
.unwrap() .unwrap()

View File

@@ -1,6 +1,10 @@
use std::{collections::HashMap, path::PathBuf}; use std::{
collections::HashMap,
path::{Path, PathBuf},
};
use anyhow::{format_err, Context}; use anyhow::{format_err, Context};
use memofs::{IoResultExt as _, Vfs};
use rbx_dom_weak::{types::Attributes, Ustr, UstrMap}; use rbx_dom_weak::{types::Attributes, Ustr, UstrMap};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -33,7 +37,38 @@ pub struct AdjacentMetadata {
} }
impl AdjacentMetadata { impl AdjacentMetadata {
pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> { /// Attempts to read a meta file for the provided path and name, and if
/// one exists applies it.
///
/// Also inserts the potential metadata paths into the snapshot's relevant
/// paths for convenience purposes.
pub fn read_and_apply_all(
vfs: &Vfs,
path: &Path,
name: &str,
snapshot: &mut InstanceSnapshot,
) -> anyhow::Result<()> {
let meta_path_json = path.with_file_name(format!("{name}.meta.json"));
let meta_path_jsonc = path.with_file_name(format!("{name}.meta.jsonc"));
if let Some(meta_contents) = vfs.read(&meta_path_json).with_not_found()? {
let mut metadata = Self::from_slice(&meta_contents, meta_path_json.clone())?;
metadata.apply_all(snapshot)?;
}
if let Some(meta_contents) = vfs.read(&meta_path_jsonc).with_not_found()? {
let mut metadata = Self::from_slice(&meta_contents, meta_path_json.clone())?;
metadata.apply_all(snapshot)?;
}
// Rather than pushing these in the snapshot middleware, we can just do it here.
snapshot.metadata.relevant_paths.push(meta_path_json);
snapshot.metadata.relevant_paths.push(meta_path_jsonc);
Ok(())
}
fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> {
let mut meta: Self = json::from_slice_with_context(slice, || { let mut meta: Self = json::from_slice_with_context(slice, || {
format!( format!(
"File contained malformed .meta.json data: {}", "File contained malformed .meta.json data: {}",
@@ -130,7 +165,37 @@ pub struct DirectoryMetadata {
} }
impl DirectoryMetadata { impl DirectoryMetadata {
pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> { /// Attempts to read an `init.meta`` file for the provided path, and if
/// one exists applies it.
///
/// Also inserts the potential metadata paths into the snapshot's relevant
/// paths for convenience purposes.
pub fn read_and_apply_all(
vfs: &Vfs,
path: &Path,
snapshot: &mut InstanceSnapshot,
) -> anyhow::Result<()> {
let meta_path_json = path.join("init.meta.json");
let meta_path_jsonc = path.join("init.meta.jsonc");
if let Some(meta_contents) = vfs.read(&meta_path_json).with_not_found()? {
let mut metadata = Self::from_slice(&meta_contents, meta_path_json.clone())?;
metadata.apply_all(snapshot)?;
}
if let Some(meta_contents) = vfs.read(&meta_path_jsonc).with_not_found()? {
let mut metadata = Self::from_slice(&meta_contents, meta_path_jsonc.clone())?;
metadata.apply_all(snapshot)?;
}
// Rather than pushing these in the snapshot middleware, we can just do it here.
snapshot.metadata.relevant_paths.push(meta_path_json);
snapshot.metadata.relevant_paths.push(meta_path_jsonc);
Ok(())
}
fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> {
let mut meta: Self = json::from_slice_with_context(slice, || { let mut meta: Self = json::from_slice_with_context(slice, || {
format!( format!(
"File contained malformed init.meta.json data: {}", "File contained malformed init.meta.json data: {}",
@@ -211,3 +276,82 @@ impl DirectoryMetadata {
Ok(()) Ok(())
} }
} }
#[cfg(test)]
mod test {
use memofs::{InMemoryFs, VfsSnapshot};
use super::*;
#[test]
fn adjacent_read_json() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/foo/bar.meta.json",
VfsSnapshot::file(r#"{"id": "manually specified"}"#),
)
.unwrap();
let vfs = Vfs::new(imfs);
let path = Path::new("/foo/bar.rojo");
let mut snapshot = InstanceSnapshot::new();
AdjacentMetadata::read_and_apply_all(&vfs, path, "bar", &mut snapshot).unwrap();
insta::assert_yaml_snapshot!(snapshot);
}
#[test]
fn adjacent_read_jsonc() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/foo/bar.meta.jsonc",
VfsSnapshot::file(r#"{"id": "manually specified"}"#),
)
.unwrap();
let vfs = Vfs::new(imfs);
let path = Path::new("/foo/bar.rojo");
let mut snapshot = InstanceSnapshot::new();
AdjacentMetadata::read_and_apply_all(&vfs, path, "bar", &mut snapshot).unwrap();
insta::assert_yaml_snapshot!(snapshot);
}
#[test]
fn directory_read_json() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/foo/init.meta.json",
VfsSnapshot::file(r#"{"id": "manually specified"}"#),
)
.unwrap();
let vfs = Vfs::new(imfs);
let path = Path::new("/foo/");
let mut snapshot = InstanceSnapshot::new();
DirectoryMetadata::read_and_apply_all(&vfs, path, &mut snapshot).unwrap();
insta::assert_yaml_snapshot!(snapshot);
}
#[test]
fn directory_read_jsonc() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/foo/init.meta.jsonc",
VfsSnapshot::file(r#"{"id": "manually specified"}"#),
)
.unwrap();
let vfs = Vfs::new(imfs);
let path = Path::new("/foo/");
let mut snapshot = InstanceSnapshot::new();
DirectoryMetadata::read_and_apply_all(&vfs, path, &mut snapshot).unwrap();
insta::assert_yaml_snapshot!(snapshot);
}
}

View File

@@ -28,8 +28,8 @@ use anyhow::Context;
use memofs::{IoResultExt, Vfs}; use memofs::{IoResultExt, Vfs};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::glob::Glob;
use crate::snapshot::{InstanceContext, InstanceSnapshot, SyncRule}; use crate::snapshot::{InstanceContext, InstanceSnapshot, SyncRule};
use crate::{glob::Glob, project::DEFAULT_PROJECT_NAMES};
use self::{ use self::{
csv::{snapshot_csv, snapshot_csv_init}, csv::{snapshot_csv, snapshot_csv_init},
@@ -122,9 +122,11 @@ pub fn snapshot_from_vfs(
fn get_init_path<P: AsRef<Path>>(vfs: &Vfs, dir: P) -> anyhow::Result<Option<PathBuf>> { fn get_init_path<P: AsRef<Path>>(vfs: &Vfs, dir: P) -> anyhow::Result<Option<PathBuf>> {
let path = dir.as_ref(); let path = dir.as_ref();
let project_path = path.join("default.project.json"); for default_project_name in DEFAULT_PROJECT_NAMES {
if vfs.metadata(&project_path).with_not_found()?.is_some() { let project_path = path.join(default_project_name);
return Ok(Some(project_path)); if vfs.metadata(&project_path).with_not_found()?.is_some() {
return Ok(Some(project_path));
}
} }
let init_path = path.join("init.luau"); let init_path = path.join("init.luau");
@@ -312,8 +314,11 @@ pub fn default_sync_rules() -> &'static [SyncRule] {
sync_rule!("*.plugin.luau", PluginScript, ".plugin.luau"), sync_rule!("*.plugin.luau", PluginScript, ".plugin.luau"),
sync_rule!("*.{lua,luau}", ModuleScript), sync_rule!("*.{lua,luau}", ModuleScript),
sync_rule!("*.project.json", Project, ".project.json"), sync_rule!("*.project.json", Project, ".project.json"),
sync_rule!("*.project.jsonc", Project, ".project.jsonc"),
sync_rule!("*.model.json", JsonModel, ".model.json"), sync_rule!("*.model.json", JsonModel, ".model.json"),
sync_rule!("*.model.jsonc", JsonModel, ".model.jsonc"),
sync_rule!("*.json", Json, ".json", "*.meta.json"), sync_rule!("*.json", Json, ".json", "*.meta.json"),
sync_rule!("*.jsonc", Json, ".jsonc", "*.meta.jsonc"),
sync_rule!("*.toml", Toml), sync_rule!("*.toml", Toml),
sync_rule!("*.csv", Csv), sync_rule!("*.csv", Csv),
sync_rule!("*.txt", Text), sync_rule!("*.txt", Text),

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.csv - /foo.csv
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Contents: Contents:
String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]"
children: [] children: []

View File

@@ -0,0 +1,29 @@
---
source: src/snapshot_middleware/csv.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: /root
relevant_paths:
- /root
- /root/init.lua
- /root/init.luau
- /root/init.server.lua
- /root/init.server.luau
- /root/init.client.lua
- /root/init.client.luau
- /root/init.csv
- /root/init.meta.json
- /root/init.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: ~
name: root
class_name: LocalizationTable
properties:
Contents:
String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]"
children: []

View File

@@ -0,0 +1,29 @@
---
source: src/snapshot_middleware/csv.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: /root
relevant_paths:
- /root
- /root/init.lua
- /root/init.luau
- /root/init.server.lua
- /root/init.server.luau
- /root/init.client.lua
- /root/init.client.luau
- /root/init.csv
- /root/init.meta.json
- /root/init.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: root
class_name: LocalizationTable
properties:
Contents:
String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]"
children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.csv - /foo.csv
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Contents: Contents:
String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]"
children: [] children: []

View File

@@ -9,7 +9,6 @@ metadata:
Path: /foo Path: /foo
relevant_paths: relevant_paths:
- /foo - /foo
- /foo/init.meta.json
- /foo/init.lua - /foo/init.lua
- /foo/init.luau - /foo/init.luau
- /foo/init.server.lua - /foo/init.server.lua
@@ -17,6 +16,8 @@ metadata:
- /foo/init.client.lua - /foo/init.client.lua
- /foo/init.client.luau - /foo/init.client.luau
- /foo/init.csv - /foo/init.csv
- /foo/init.meta.json
- /foo/init.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -24,4 +25,3 @@ name: foo
class_name: Folder class_name: Folder
properties: {} properties: {}
children: [] children: []

View File

@@ -9,7 +9,6 @@ metadata:
Path: /foo Path: /foo
relevant_paths: relevant_paths:
- /foo - /foo
- /foo/init.meta.json
- /foo/init.lua - /foo/init.lua
- /foo/init.luau - /foo/init.luau
- /foo/init.server.lua - /foo/init.server.lua
@@ -17,6 +16,8 @@ metadata:
- /foo/init.client.lua - /foo/init.client.lua
- /foo/init.client.luau - /foo/init.client.luau
- /foo/init.csv - /foo/init.csv
- /foo/init.meta.json
- /foo/init.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -31,7 +32,6 @@ children:
Path: /foo/Child Path: /foo/Child
relevant_paths: relevant_paths:
- /foo/Child - /foo/Child
- /foo/Child/init.meta.json
- /foo/Child/init.lua - /foo/Child/init.lua
- /foo/Child/init.luau - /foo/Child/init.luau
- /foo/Child/init.server.lua - /foo/Child/init.server.lua
@@ -39,6 +39,8 @@ children:
- /foo/Child/init.client.lua - /foo/Child/init.client.lua
- /foo/Child/init.client.luau - /foo/Child/init.client.luau
- /foo/Child/init.csv - /foo/Child/init.csv
- /foo/Child/init.meta.json
- /foo/Child/init.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -46,4 +48,3 @@ children:
class_name: Folder class_name: Folder
properties: {} properties: {}
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.json - /foo.json
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Source: Source:
String: "return {\n\t[\"1invalidident\"] = \"nice\",\n\tarray = {1, 2, 3},\n\t[\"false\"] = false,\n\tfloat = 1234.5452,\n\tint = 1234,\n\tnull = nil,\n\tobject = {\n\t\thello = \"world\",\n\t},\n\t[\"true\"] = true,\n}" String: "return {\n\t[\"1invalidident\"] = \"nice\",\n\tarray = {1, 2, 3},\n\t[\"false\"] = false,\n\tfloat = 1234.5452,\n\tint = 1234,\n\tnull = nil,\n\tobject = {\n\t\thello = \"world\",\n\t},\n\t[\"true\"] = true,\n}"
children: [] children: []

View File

@@ -0,0 +1,22 @@
---
source: src/snapshot_middleware/json.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: /foo.json
relevant_paths:
- /foo.json
- /foo.meta.json
- /foo.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: foo
class_name: ModuleScript
properties:
Source:
String: "return {\n\tarray = {1, 2, 3},\n\tfloat = 1234.5452,\n\tint = 1234,\n}"
children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.client.lua - /foo.client.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.lua - /foo.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.lua - /foo.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /bar.server.lua - /bar.server.lua
- /bar.meta.json - /bar.meta.json
- /bar.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -23,4 +24,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.server.lua - /foo.server.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -21,4 +22,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.server.lua - /foo.server.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -21,4 +22,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -2,23 +2,28 @@
source: src/snapshot_middleware/lua.rs source: src/snapshot_middleware/lua.rs
expression: instance_snapshot expression: instance_snapshot
--- ---
snapshot_id: ~ snapshot_id: "00000000000000000000000000000000"
metadata: metadata:
ignore_unknown_instances: false ignore_unknown_instances: false
instigating_source: instigating_source:
Path: /root Path: /root
relevant_paths: relevant_paths:
- /root - /root
- /root/init.meta.json
- /root/init.lua - /root/init.lua
- /root/init.luau
- /root/init.server.lua - /root/init.server.lua
- /root/init.server.luau
- /root/init.client.lua - /root/init.client.lua
- /root/init.client.luau
- /root/init.csv
- /root/init.meta.json
- /root/init.meta.jsonc
context: context:
script_type: Class emit_legacy_scripts: true
specified_id: ~
name: root name: root
class_name: ModuleScript class_name: ModuleScript
properties: properties:
Source: Source:
Type: String String: Hello!
Value: Hello!
children: [] children: []

View File

@@ -0,0 +1,29 @@
---
source: src/snapshot_middleware/lua.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: /root
relevant_paths:
- /root
- /root/init.lua
- /root/init.luau
- /root/init.server.lua
- /root/init.server.luau
- /root/init.client.lua
- /root/init.client.luau
- /root/init.csv
- /root/init.meta.json
- /root/init.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: root
class_name: ModuleScript
properties:
Source:
String: Hello!
children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.plugin.lua - /foo.plugin.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: false emit_legacy_scripts: false
specified_id: ~ specified_id: ~

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.client.lua - /foo.client.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: false emit_legacy_scripts: false
specified_id: ~ specified_id: ~
@@ -21,4 +22,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.lua - /foo.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: false emit_legacy_scripts: false
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.lua - /foo.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: false emit_legacy_scripts: false
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /bar.server.lua - /bar.server.lua
- /bar.meta.json - /bar.meta.json
- /bar.meta.jsonc
context: context:
emit_legacy_scripts: false emit_legacy_scripts: false
specified_id: ~ specified_id: ~
@@ -23,4 +24,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.server.lua - /foo.server.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: false emit_legacy_scripts: false
specified_id: ~ specified_id: ~
@@ -21,4 +22,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.server.lua - /foo.server.lua
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: false emit_legacy_scripts: false
specified_id: ~ specified_id: ~
@@ -21,4 +22,3 @@ properties:
Source: Source:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -0,0 +1,17 @@
---
source: src/snapshot_middleware/meta_file.rs
expression: snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
relevant_paths:
- /foo/bar.meta.json
- /foo/bar.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: DEFAULT
class_name: DEFAULT
properties: {}
children: []

View File

@@ -0,0 +1,17 @@
---
source: src/snapshot_middleware/meta_file.rs
expression: snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
relevant_paths:
- /foo/bar.meta.json
- /foo/bar.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: DEFAULT
class_name: DEFAULT
properties: {}
children: []

View File

@@ -0,0 +1,17 @@
---
source: src/snapshot_middleware/meta_file.rs
expression: snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
relevant_paths:
- /foo/init.meta.json
- /foo/init.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: DEFAULT
class_name: DEFAULT
properties: {}
children: []

View File

@@ -0,0 +1,17 @@
---
source: src/snapshot_middleware/meta_file.rs
expression: snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
relevant_paths:
- /foo/init.meta.json
- /foo/init.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: DEFAULT
class_name: DEFAULT
properties: {}
children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo/other.txt - /foo/other.txt
- /foo/other.meta.json - /foo/other.meta.json
- /foo/other.meta.jsonc
- /foo/default.project.json - /foo/default.project.json
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
@@ -20,4 +21,3 @@ properties:
Value: Value:
String: "Hello, world!" String: "Hello, world!"
children: [] children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.toml - /foo.toml
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Source: Source:
String: "return {\n\t[\"1invalidident\"] = \"nice\",\n\tarray = {1, 2, 3},\n\tdates = {\n\t\tlocaldate = \"1979-05-27\",\n\t\tlocaldatetime = \"1979-05-27T07:32:00\",\n\t\tlocaltime = \"00:32:00.999999\",\n\t\toffset1 = \"1979-05-27T00:32:00.999999-07:00\",\n\t\toffset2 = \"1979-05-27T07:32:00Z\",\n\t},\n\t[\"false\"] = false,\n\tfloat = 1234.5452,\n\tint = 1234,\n\tobject = {\n\t\thello = \"world\",\n\t},\n\t[\"true\"] = true,\n}" String: "return {\n\t[\"1invalidident\"] = \"nice\",\n\tarray = {1, 2, 3},\n\tdates = {\n\t\tlocaldate = \"1979-05-27\",\n\t\tlocaldatetime = \"1979-05-27T07:32:00\",\n\t\tlocaltime = \"00:32:00.999999\",\n\t\toffset1 = \"1979-05-27T00:32:00.999999-07:00\",\n\t\toffset2 = \"1979-05-27T07:32:00Z\",\n\t},\n\t[\"false\"] = false,\n\tfloat = 1234.5452,\n\tint = 1234,\n\tobject = {\n\t\thello = \"world\",\n\t},\n\t[\"true\"] = true,\n}"
children: [] children: []

View File

@@ -0,0 +1,22 @@
---
source: src/snapshot_middleware/toml.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: foo.toml
relevant_paths:
- foo.toml
- foo.meta.json
- foo.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: foo
class_name: ModuleScript
properties:
Source:
String: "return {\n\tarray = {1, 2, 3},\n\tbool = false,\n\tint = 123,\n}"
children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.txt - /foo.txt
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~
@@ -19,4 +20,3 @@ properties:
Value: Value:
String: Hello there! String: Hello there!
children: [] children: []

View File

@@ -0,0 +1,22 @@
---
source: src/snapshot_middleware/txt.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: /foo.txt
relevant_paths:
- /foo.txt
- /foo.meta.json
- /foo.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: foo
class_name: StringValue
properties:
Value:
String: Hello there!
children: []

View File

@@ -10,6 +10,7 @@ metadata:
relevant_paths: relevant_paths:
- /foo.yaml - /foo.yaml
- /foo.meta.json - /foo.meta.json
- /foo.meta.jsonc
context: context:
emit_legacy_scripts: true emit_legacy_scripts: true
specified_id: ~ specified_id: ~

View File

@@ -0,0 +1,22 @@
---
source: src/snapshot_middleware/yaml.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: foo.yaml
relevant_paths:
- foo.yaml
- foo.meta.json
- foo.meta.jsonc
context:
emit_legacy_scripts: true
specified_id: manually specified
name: foo
class_name: ModuleScript
properties:
Source:
String: "return {\n\tvalue = 1234,\n}"
children: []

View File

@@ -1,7 +1,7 @@
use std::path::Path; use std::path::Path;
use anyhow::Context; use anyhow::Context;
use memofs::{IoResultExt, Vfs}; use memofs::Vfs;
use rbx_dom_weak::ustr; use rbx_dom_weak::ustr;
use crate::{ use crate::{
@@ -24,8 +24,6 @@ pub fn snapshot_toml(
let as_lua = toml_to_lua(value).to_string(); let as_lua = toml_to_lua(value).to_string();
let meta_path = path.with_file_name(format!("{}.meta.json", name));
let mut snapshot = InstanceSnapshot::new() let mut snapshot = InstanceSnapshot::new()
.name(name) .name(name)
.class_name("ModuleScript") .class_name("ModuleScript")
@@ -33,14 +31,11 @@ pub fn snapshot_toml(
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()
.instigating_source(path) .instigating_source(path)
.relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) .relevant_paths(vec![path.to_path_buf()])
.context(context), .context(context),
); );
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { AdjacentMetadata::read_and_apply_all(vfs, path, name, &mut snapshot)?;
let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?;
metadata.apply_all(&mut snapshot)?;
}
Ok(Some(snapshot)) Ok(Some(snapshot))
} }
@@ -117,4 +112,42 @@ mod test {
insta::assert_yaml_snapshot!(instance_snapshot); insta::assert_yaml_snapshot!(instance_snapshot);
} }
#[test]
fn with_metadata() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"foo.toml",
VfsSnapshot::file(
r#"
array = [1, 2, 3]
int = 123
bool = false
"#,
),
)
.unwrap();
imfs.load_snapshot(
"foo.meta.json",
VfsSnapshot::file(
r#"{
"id": "manually specified"
}"#,
),
)
.unwrap();
let vfs = Vfs::new(imfs.clone());
let instance_snapshot = snapshot_toml(
&InstanceContext::default(),
&vfs,
Path::new("foo.toml"),
"foo",
)
.unwrap()
.unwrap();
insta::assert_yaml_snapshot!(instance_snapshot);
}
} }

View File

@@ -1,6 +1,6 @@
use std::{path::Path, str}; use std::{path::Path, str};
use memofs::{IoResultExt, Vfs}; use memofs::Vfs;
use rbx_dom_weak::ustr; use rbx_dom_weak::ustr;
use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot};
@@ -16,8 +16,6 @@ pub fn snapshot_txt(
let contents = vfs.read_to_string(path)?; let contents = vfs.read_to_string(path)?;
let contents_str = contents.as_str(); let contents_str = contents.as_str();
let meta_path = path.with_file_name(format!("{}.meta.json", name));
let mut snapshot = InstanceSnapshot::new() let mut snapshot = InstanceSnapshot::new()
.name(name) .name(name)
.class_name("StringValue") .class_name("StringValue")
@@ -25,14 +23,11 @@ pub fn snapshot_txt(
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()
.instigating_source(path) .instigating_source(path)
.relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) .relevant_paths(vec![path.to_path_buf()])
.context(context), .context(context),
); );
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { AdjacentMetadata::read_and_apply_all(vfs, path, name, &mut snapshot)?;
let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?;
metadata.apply_all(&mut snapshot)?;
}
Ok(Some(snapshot)) Ok(Some(snapshot))
} }
@@ -62,4 +57,32 @@ mod test {
insta::assert_yaml_snapshot!(instance_snapshot); insta::assert_yaml_snapshot!(instance_snapshot);
} }
#[test]
fn with_metadata() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot("/foo.txt", VfsSnapshot::file("Hello there!"))
.unwrap();
imfs.load_snapshot(
"/foo.meta.json",
VfsSnapshot::file(
r#"{
"id": "manually specified"
}"#,
),
)
.unwrap();
let vfs = Vfs::new(imfs.clone());
let instance_snapshot = snapshot_txt(
&InstanceContext::default(),
&vfs,
Path::new("/foo.txt"),
"foo",
)
.unwrap()
.unwrap();
insta::assert_yaml_snapshot!(instance_snapshot);
}
} }

View File

@@ -1,7 +1,7 @@
use std::path::Path; use std::path::Path;
use anyhow::Context as _; use anyhow::Context as _;
use memofs::{IoResultExt, Vfs}; use memofs::Vfs;
use rbx_dom_weak::ustr; use rbx_dom_weak::ustr;
use yaml_rust2::{Yaml, YamlLoader}; use yaml_rust2::{Yaml, YamlLoader};
@@ -30,8 +30,6 @@ pub fn snapshot_yaml(
let as_lua = Statement::Return(yaml_to_luau(value)?); let as_lua = Statement::Return(yaml_to_luau(value)?);
let meta_path = path.with_file_name(format!("{}.meta.json", name));
let mut snapshot = InstanceSnapshot::new() let mut snapshot = InstanceSnapshot::new()
.name(name) .name(name)
.class_name("ModuleScript") .class_name("ModuleScript")
@@ -39,14 +37,11 @@ pub fn snapshot_yaml(
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()
.instigating_source(path) .instigating_source(path)
.relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) .relevant_paths(vec![path.to_path_buf()])
.context(context), .context(context),
); );
if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { AdjacentMetadata::read_and_apply_all(vfs, path, name, &mut snapshot)?;
let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?;
metadata.apply_all(&mut snapshot)?;
}
Ok(Some(snapshot)) Ok(Some(snapshot))
} }
@@ -231,4 +226,40 @@ value: 9007199254740993
.unwrap() .unwrap()
.unwrap(); .unwrap();
} }
#[test]
fn with_metadata() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"foo.yaml",
VfsSnapshot::file(
r#"
value: 1234
"#,
),
)
.unwrap();
imfs.load_snapshot(
"foo.meta.json",
VfsSnapshot::file(
r#"{
"id": "manually specified",
}"#,
),
)
.unwrap();
let vfs = Vfs::new(imfs.clone());
let instance_snapshot = snapshot_yaml(
&InstanceContext::default(),
&vfs,
Path::new("foo.yaml"),
"foo",
)
.unwrap()
.unwrap();
insta::assert_yaml_snapshot!(instance_snapshot);
}
} }