diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index b505e793..a8f27180 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -7,15 +7,16 @@ use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::meta_file::AdjacentMetadata; +use super::{meta_file::AdjacentMetadata, util::PathExt}; pub fn snapshot_csv( _context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let name = path.file_name_trim_end(".csv")?; + + let meta_path = path.with_file_name(format!("{}.meta.json", name)); let contents = vfs.read(path)?; let table_contents = convert_localization_csv(&contents).with_context(|| { @@ -26,7 +27,7 @@ pub fn snapshot_csv( })?; let mut snapshot = InstanceSnapshot::new() - .name(instance_name) + .name(name) .class_name("LocalizationTable") .properties(hashmap! { "Contents".to_owned() => table_contents.into(), @@ -143,14 +144,10 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = snapshot_csv( - &InstanceContext::default(), - &mut vfs, - Path::new("/foo.csv"), - "foo", - ) - .unwrap() - .unwrap(); + let instance_snapshot = + snapshot_csv(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -175,14 +172,10 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = snapshot_csv( - &InstanceContext::default(), - &mut vfs, - Path::new("/foo.csv"), - "foo", - ) - .unwrap() - .unwrap(); + let instance_snapshot = + snapshot_csv(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs index 7530812d..8c7f369e 100644 --- a/src/snapshot_middleware/json.rs +++ b/src/snapshot_middleware/json.rs @@ -9,14 +9,14 @@ use crate::{ snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, }; -use super::meta_file::AdjacentMetadata; +use super::{meta_file::AdjacentMetadata, util::PathExt}; pub fn snapshot_json( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".json")?; let contents = vfs.read(path)?; let value: serde_json::Value = serde_json::from_slice(&contents) @@ -28,10 +28,10 @@ pub fn snapshot_json( "Source".to_owned() => as_lua.into(), }; - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", name)); let mut snapshot = InstanceSnapshot::new() - .name(instance_name) + .name(name) .class_name("ModuleScript") .properties(properties) .metadata( @@ -107,7 +107,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.json"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 89b274d4..52071031 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -9,12 +9,15 @@ use crate::{ snapshot::{InstanceContext, InstanceSnapshot}, }; +use super::util::PathExt; + pub fn snapshot_json_model( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".model.json")?; + let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))?; @@ -28,7 +31,7 @@ pub fn snapshot_json_model( let mut snapshot = instance .core - .into_snapshot(instance_name.to_owned()) + .into_snapshot(name.to_owned()) .with_context(|| format!("Could not load JSON model: {}", path.display()))?; snapshot.metadata = snapshot @@ -133,7 +136,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.model.json"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 9ce40c95..36729f8f 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -33,7 +33,7 @@ use self::{ rbxm::snapshot_rbxm, rbxmx::snapshot_rbxmx, txt::snapshot_txt, - util::match_file_name, + util::PathExt, }; pub use self::project::snapshot_project_node; @@ -73,7 +73,7 @@ pub fn snapshot_from_vfs( snapshot_dir(context, vfs, path) } else { - if let Some(name) = match_file_name(path, ".lua") { + if let Ok(name) = path.file_name_trim_end(".lua") { match name { // init scripts are handled elsewhere and should not turn into // their own children. @@ -81,23 +81,23 @@ pub fn snapshot_from_vfs( _ => return snapshot_lua(context, vfs, path), } - } else if let Some(_name) = match_file_name(path, ".project.json") { + } else if path.file_name_ends_with(".project.json") { return snapshot_project(context, vfs, path); - } else if let Some(name) = match_file_name(path, ".model.json") { - return snapshot_json_model(context, vfs, path, name); - } else if let Some(_name) = match_file_name(path, ".meta.json") { + } else if path.file_name_ends_with(".model.json") { + return snapshot_json_model(context, vfs, path); + } else if path.file_name_ends_with(".meta.json") { // .meta.json files do not turn into their own instances. return Ok(None); - } else if let Some(name) = match_file_name(path, ".json") { - return snapshot_json(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".csv") { - return snapshot_csv(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".txt") { - return snapshot_txt(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".rbxmx") { - return snapshot_rbxmx(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".rbxm") { - return snapshot_rbxm(context, vfs, path, name); + } else if path.file_name_ends_with(".json") { + return snapshot_json(context, vfs, path); + } else if path.file_name_ends_with(".csv") { + return snapshot_csv(context, vfs, path); + } else if path.file_name_ends_with(".txt") { + return snapshot_txt(context, vfs, path); + } else if path.file_name_ends_with(".rbxmx") { + return snapshot_rbxmx(context, vfs, path); + } else if path.file_name_ends_with(".rbxm") { + return snapshot_rbxm(context, vfs, path); } Ok(None) diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 8ec551d2..b1d61313 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -5,12 +5,15 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; +use super::util::PathExt; + pub fn snapshot_rbxm( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".rbxm")?; + let temp_tree = rbx_binary::from_reader(vfs.read(path)?.as_slice()) .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; @@ -19,7 +22,7 @@ pub fn snapshot_rbxm( if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) - .name(instance_name) + .name(name) .metadata( InstanceMetadata::new() .instigating_source(path) @@ -58,7 +61,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxm"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index c37d3ddf..3cdd52e4 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -5,12 +5,15 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; +use super::util::PathExt; + pub fn snapshot_rbxmx( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".rbxmx")?; + let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); @@ -22,7 +25,7 @@ pub fn snapshot_rbxmx( if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) - .name(instance_name) + .name(name) .metadata( InstanceMetadata::new() .instigating_source(path) @@ -71,7 +74,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxmx"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index fbc42dd6..13d5b990 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -6,14 +6,15 @@ use memofs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::meta_file::AdjacentMetadata; +use super::{meta_file::AdjacentMetadata, util::PathExt}; pub fn snapshot_txt( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".txt")?; + let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? @@ -23,10 +24,10 @@ pub fn snapshot_txt( "Value".to_owned() => contents_str.into(), }; - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", name)); let mut snapshot = InstanceSnapshot::new() - .name(instance_name) + .name(name) .class_name("StringValue") .properties(properties) .metadata( @@ -58,14 +59,10 @@ mod test { let mut vfs = Vfs::new(imfs.clone()); - let instance_snapshot = snapshot_txt( - &InstanceContext::default(), - &mut vfs, - Path::new("/foo.txt"), - "foo", - ) - .unwrap() - .unwrap(); + let instance_snapshot = + snapshot_txt(&InstanceContext::default(), &mut vfs, Path::new("/foo.txt")) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/util.rs b/src/snapshot_middleware/util.rs index 153c31c2..517cd606 100644 --- a/src/snapshot_middleware/util.rs +++ b/src/snapshot_middleware/util.rs @@ -1,5 +1,7 @@ use std::path::Path; +use anyhow::Context; + /// If the given string ends up with the given suffix, returns the portion of /// the string before the suffix. pub fn match_trailing<'a>(input: &'a str, suffix: &str) -> Option<&'a str> { @@ -11,10 +13,31 @@ pub fn match_trailing<'a>(input: &'a str, suffix: &str) -> Option<&'a str> { } } -/// If the given path has a file name, and that file name ends with the given -/// suffix, returns the portion of the file name before the given suffix. -pub fn match_file_name<'a>(path: &'a Path, suffix: &str) -> Option<&'a str> { - let file_name = path.file_name()?.to_str()?; - - match_trailing(&file_name, suffix) +pub trait PathExt { + fn file_name_ends_with(&self, suffix: &str) -> bool; + fn file_name_trim_end<'a>(&'a self, suffix: &str) -> anyhow::Result<&'a str>; +} + +impl

PathExt for P +where + P: AsRef, +{ + fn file_name_ends_with(&self, suffix: &str) -> bool { + self.as_ref() + .file_name() + .and_then(|name| name.to_str()) + .map(|name| name.ends_with(suffix)) + .unwrap_or(false) + } + + fn file_name_trim_end<'a>(&'a self, suffix: &str) -> anyhow::Result<&'a str> { + let path = self.as_ref(); + let file_name = path + .file_name() + .and_then(|name| name.to_str()) + .with_context(|| format!("Path did not have a file name: {}", path.display()))?; + + match_trailing(&file_name, suffix) + .with_context(|| format!("Path did not end in {}: {}", suffix, path.display())) + } }