From 6d8c85682dc77f034627ff8699f5dafcd4471acb Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 19 Dec 2025 22:50:53 -0600 Subject: [PATCH] Implement encoding and decoding for Windows-invalid characters in file names - Added `encode_path_name` and `decode_path_name` functions to handle encoding and decoding of invalid characters. - Updated `SyncbackRules` to include an option for encoding Windows-invalid characters during syncback. - Modified `name_for_inst` to conditionally encode invalid characters based on the new option. - Adjusted `ServeSession` and `InstanceContext` to support the new encoding feature. - Updated tests and snapshots to reflect changes in encoding behavior. --- src/json.rs | 34 +--- src/lib.rs | 1 + src/path_encoding.rs | 157 ++++++++++++++++++ src/serve_session.rs | 9 +- src/snapshot/metadata.rs | 10 ++ ..._snapshot__tests__apply__add_property.snap | 1 + ...s__apply__remove_property_after_patch.snap | 1 + ...tests__apply__remove_property_initial.snap | 1 + ...tests__apply__set_name_and_class_name.snap | 1 + ...__snapshot__tests__compute__add_child.snap | 1 + src/snapshot_middleware/dir.rs | 9 + src/snapshot_middleware/mod.rs | 33 ++-- ...t_middleware__csv__test__csv_from_vfs.snap | 1 + ...pshot_middleware__csv__test__csv_init.snap | 1 + ...leware__csv__test__csv_init_with_meta.snap | 1 + ..._middleware__csv__test__csv_with_meta.snap | 1 + ...t_middleware__dir__test__empty_folder.snap | 1 + ...ddleware__dir__test__folder_in_folder.snap | 2 + ...leware__json__test__instance_from_vfs.snap | 1 + ...middleware__json__test__with_metadata.snap | 1 + ...are__json_model__test__model_from_vfs.snap | 2 + ...on_model__test__model_from_vfs_legacy.snap | 2 + ...are__lua__test__class_client_from_vfs.snap | 1 + ...are__lua__test__class_module_from_vfs.snap | 1 + ...re__lua__test__class_module_with_meta.snap | 1 + ...are__lua__test__class_script_disabled.snap | 1 + ...re__lua__test__class_script_with_meta.snap | 1 + ...are__lua__test__class_server_from_vfs.snap | 1 + ...ware__lua__test__init_module_from_vfs.snap | 1 + ..._test__init_module_from_vfs_with_meta.snap | 1 + ...re__lua__test__plugin_module_from_vfs.snap | 1 + ...lua__test__runcontext_client_from_vfs.snap | 1 + ...lua__test__runcontext_module_from_vfs.snap | 1 + ...ua__test__runcontext_module_with_meta.snap | 1 + ...lua__test__runcontext_script_disabled.snap | 1 + ...ua__test__runcontext_script_with_meta.snap | 1 + ...lua__test__runcontext_server_from_vfs.snap | 1 + ...__meta_file__test__adjacent_read_json.snap | 1 + ..._meta_file__test__adjacent_read_jsonc.snap | 1 + ..._meta_file__test__directory_read_json.snap | 1 + ...meta_file__test__directory_read_jsonc.snap | 1 + ...eware__project__test__no_name_project.snap | 1 + ...oject__test__project_from_direct_file.snap | 1 + ...test__project_path_property_overrides.snap | 1 + ..._project__test__project_with_children.snap | 2 + ...t__test__project_with_path_to_project.snap | 1 + ...ct_with_path_to_project_with_children.snap | 2 + ...oject__test__project_with_path_to_txt.snap | 1 + ...est__project_with_resolved_properties.snap | 1 + ...t__project_with_unresolved_properties.snap | 1 + ...leware__toml__test__instance_from_vfs.snap | 1 + ...middleware__toml__test__with_metadata.snap | 1 + ...dleware__txt__test__instance_from_vfs.snap | 1 + ..._middleware__txt__test__with_metadata.snap | 1 + ...leware__yaml__test__instance_from_vfs.snap | 1 + ...middleware__yaml__test__with_metadata.snap | 1 + src/syncback/file_names.rs | 39 ++++- src/syncback/mod.rs | 13 ++ src/syncback/snapshot.rs | 44 ++++- 59 files changed, 350 insertions(+), 53 deletions(-) create mode 100644 src/path_encoding.rs diff --git a/src/json.rs b/src/json.rs index 317d477a..bf079d82 100644 --- a/src/json.rs +++ b/src/json.rs @@ -166,19 +166,6 @@ pub fn to_vec_pretty_sorted(value: &T) -> anyhow::Result> serde_json::to_vec_pretty(&sorted_value).context("Failed to serialize to JSON") } -/// Serialize a value to a pretty-printed JSON string with sorted keys. -/// -/// This ensures deterministic output by sorting all object keys alphabetically, -/// which is especially useful for version control and syncback operations. -/// -/// # Errors -/// -/// Returns an error if the value cannot be serialized to JSON. -pub fn to_string_pretty_sorted(value: &T) -> anyhow::Result { - let json_value = serde_json::to_value(value).context("Failed to convert to JSON value")?; - let sorted_value = sort_json_value(json_value); - serde_json::to_string_pretty(&sorted_value).context("Failed to serialize to JSON") -} #[cfg(test)] mod tests { @@ -380,25 +367,6 @@ mod tests { assert!(mango_pos < zebra_pos); } - #[test] - fn test_to_string_pretty_sorted() { - use indexmap::IndexMap; - - let mut map: IndexMap = IndexMap::new(); - map.insert("zebra".to_string(), 1); - map.insert("apple".to_string(), 2); - map.insert("mango".to_string(), 3); - - let output = to_string_pretty_sorted(&map).unwrap(); - - // Keys should be in alphabetical order - let apple_pos = output.find("apple").unwrap(); - let mango_pos = output.find("mango").unwrap(); - let zebra_pos = output.find("zebra").unwrap(); - assert!(apple_pos < mango_pos); - assert!(mango_pos < zebra_pos); - } - #[test] fn test_sorted_nested_objects() { use serde::Serialize; @@ -413,7 +381,7 @@ mod tests { inner.insert("a".to_string(), 2); let nested = Nested { inner }; - let output = to_string_pretty_sorted(&nested).unwrap(); + let output = String::from_utf8(to_vec_pretty_sorted(&nested).unwrap()).unwrap(); // Inner keys should also be sorted let a_pos = output.find("\"a\"").unwrap(); diff --git a/src/lib.rs b/src/lib.rs index f1947eaa..5727197b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ mod json; mod lua_ast; mod message_queue; mod multimap; +pub mod path_encoding; mod path_serializer; mod project; mod resolution; diff --git a/src/path_encoding.rs b/src/path_encoding.rs new file mode 100644 index 00000000..34908d55 --- /dev/null +++ b/src/path_encoding.rs @@ -0,0 +1,157 @@ +//! Encoding and decoding utilities for Windows-invalid filename characters. +//! +//! Windows does not allow the following characters in file names: +//! < > : " / \ | ? * +//! +//! Windows also does not allow leading/trailing spaces in file names. +//! +//! This module provides functions to encode these characters using a %NAME% +//! format (e.g., `<` becomes `%LT%`) and decode them back. + +/// Mapping of Windows-invalid characters to their encoded representations. +const CHAR_ENCODINGS: &[(&str, &str)] = &[ + ("<", "%LT%"), + (">", "%GT%"), + (":", "%COLON%"), + ("\"", "%QUOTE%"), + ("/", "%SLASH%"), + ("\\", "%BACKSLASH%"), + ("|", "%PIPE%"), + ("?", "%QUESTION%"), + ("*", "%STAR%"), +]; + +const SPACE_ENCODING: &str = "%SPACE%"; + +/// Encodes Windows-invalid characters in a file name. +/// +/// This replaces characters like `<`, `>`, `:`, `"`, `/`, `\`, `|`, `?`, `*` +/// with their encoded representations like `%LT%`, `%GT%`, etc. +/// Leading and trailing spaces are encoded as `%SPACE%`. +pub fn encode_path_name(name: &str) -> String { + // Count leading and trailing spaces first (before any modifications) + let leading_spaces = name.len() - name.trim_start_matches(' ').len(); + let trailing_spaces = name.len() - name.trim_end_matches(' ').len(); + + // Get the middle part (without leading/trailing spaces) + let middle = &name[leading_spaces..name.len() - trailing_spaces]; + + // Encode invalid characters in the middle part + let mut encoded_middle = middle.to_string(); + for (char, encoded) in CHAR_ENCODINGS { + encoded_middle = encoded_middle.replace(char, encoded); + } + + // Build final result with encoded spaces + let encoded_prefix = SPACE_ENCODING.repeat(leading_spaces); + let encoded_suffix = SPACE_ENCODING.repeat(trailing_spaces); + + format!("{}{}{}", encoded_prefix, encoded_middle, encoded_suffix) +} + +/// Decodes encoded Windows-invalid characters back to their original form. +/// +/// This replaces encoded representations like `%LT%`, `%GT%`, etc. back +/// to their original characters `<`, `>`, etc. +/// `%SPACE%` at the start/end is decoded back to spaces. +pub fn decode_path_name(name: &str) -> String { + let mut result = name.to_string(); + + // Count and strip leading %SPACE% + let mut leading_spaces = 0; + while result.starts_with(SPACE_ENCODING) { + leading_spaces += 1; + result = result[SPACE_ENCODING.len()..].to_string(); + } + + // Count and strip trailing %SPACE% + let mut trailing_spaces = 0; + while result.ends_with(SPACE_ENCODING) { + trailing_spaces += 1; + result = result[..result.len() - SPACE_ENCODING.len()].to_string(); + } + + // Decode invalid characters in the middle + for (char, encoded) in CHAR_ENCODINGS { + result = result.replace(encoded, char); + } + + // Rebuild with actual spaces + let prefix = " ".repeat(leading_spaces); + let suffix = " ".repeat(trailing_spaces); + format!("{}{}{}", prefix, result, suffix) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_encode_all_chars() { + let input = r#"<>:"/\|?*"#; + let expected = "%LT%%GT%%COLON%%QUOTE%%SLASH%%BACKSLASH%%PIPE%%QUESTION%%STAR%"; + assert_eq!(encode_path_name(input), expected); + } + + #[test] + fn test_decode_all_chars() { + let input = "%LT%%GT%%COLON%%QUOTE%%SLASH%%BACKSLASH%%PIPE%%QUESTION%%STAR%"; + let expected = r#"<>:"/\|?*"#; + assert_eq!(decode_path_name(input), expected); + } + + #[test] + fn test_roundtrip() { + let original = "TestWith:Special\"Chars/And\\More|Stuff?Here*End"; + let encoded = encode_path_name(original); + let decoded = decode_path_name(&encoded); + assert_eq!(decoded, original); + } + + #[test] + fn test_no_special_chars() { + let input = "NormalFileName"; + assert_eq!(encode_path_name(input), input); + assert_eq!(decode_path_name(input), input); + } + + #[test] + fn test_leading_spaces() { + let input = " LeadingSpaces"; + let encoded = encode_path_name(input); + assert_eq!(encoded, "%SPACE%%SPACE%LeadingSpaces"); + assert_eq!(decode_path_name(&encoded), input); + } + + #[test] + fn test_trailing_spaces() { + let input = "TrailingSpaces "; + let encoded = encode_path_name(input); + assert_eq!(encoded, "TrailingSpaces%SPACE%%SPACE%"); + assert_eq!(decode_path_name(&encoded), input); + } + + #[test] + fn test_both_spaces() { + let input = " Both Spaces "; + let encoded = encode_path_name(input); + assert_eq!(encoded, "%SPACE%Both Spaces%SPACE%"); + assert_eq!(decode_path_name(&encoded), input); + } + + #[test] + fn test_middle_spaces_unchanged() { + let input = "Middle Spaces Here"; + let encoded = encode_path_name(input); + assert_eq!(encoded, "Middle Spaces Here"); + assert_eq!(decode_path_name(&encoded), input); + } + + #[test] + fn test_roundtrip_with_spaces() { + let original = " "; + let encoded = encode_path_name(original); + let decoded = decode_path_name(&encoded); + assert_eq!(decoded, original); + } +} diff --git a/src/serve_session.rs b/src/serve_session.rs index f50d3926..cb46e176 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -106,8 +106,15 @@ impl ServeSession { let root_id = tree.get_root_id(); - let instance_context = + let decode_windows_invalid_chars = root_project + .syncback_rules + .as_ref() + .map(|rules| rules.encode_windows_invalid_chars()) + .unwrap_or(false); + + let mut instance_context = InstanceContext::with_emit_legacy_scripts(root_project.emit_legacy_scripts); + instance_context.set_decode_windows_invalid_chars(decode_windows_invalid_chars); log::trace!("Generating snapshot of instances from VFS"); let snapshot = snapshot_from_vfs(&instance_context, &vfs, start_path)?; diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 79f7a2d0..755526ee 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -145,6 +145,11 @@ pub struct InstanceContext { pub emit_legacy_scripts: bool, #[serde(skip_serializing_if = "Vec::is_empty")] pub sync_rules: Vec, + /// Whether to decode Windows-invalid characters in file names. + /// Characters like `%LT%`, `%GT%`, `%COLON%`, etc. will be decoded + /// back to `<`, `>`, `:`, etc. in instance names sent to the plugin. + #[serde(default)] + pub decode_windows_invalid_chars: bool, } impl InstanceContext { @@ -153,6 +158,7 @@ impl InstanceContext { path_ignore_rules: Arc::new(Vec::new()), emit_legacy_scripts: emit_legacy_scripts_default().unwrap(), sync_rules: Vec::new(), + decode_windows_invalid_chars: false, } } @@ -165,6 +171,10 @@ impl InstanceContext { } } + pub fn set_decode_windows_invalid_chars(&mut self, decode: bool) { + self.decode_windows_invalid_chars = decode; + } + /// Extend the list of ignore rules in the context with the given new rules. pub fn add_path_ignore_rules(&mut self, new_rules: I) where diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap index 930119b4..128a9cea 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap @@ -13,6 +13,7 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap index fdf5ecd6..d494d159 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap @@ -11,6 +11,7 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap index b2111922..49e1c639 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap @@ -13,6 +13,7 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap index 9209a554..6fd952b7 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap @@ -11,6 +11,7 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap index 64541974..c80e67ad 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap @@ -12,6 +12,7 @@ added_instances: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 2fe2c66a..ba35225c 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -172,6 +172,11 @@ pub fn syncback_dir_no_meta<'sync>( ); continue; } + // Skip instances matching ignoreTrees + if snapshot.should_ignore_tree(*new_child_ref) { + old_child_map.remove(new_child.name.as_str()); + continue; + } if let Some(old_child) = old_child_map.remove(new_child.name.as_str()) { if old_child.metadata().relevant_paths.is_empty() { log::debug!( @@ -223,6 +228,10 @@ pub fn syncback_dir_no_meta<'sync>( ); continue; } + // Skip instances matching ignoreTrees + if snapshot.should_ignore_tree(*new_child_ref) { + continue; + } children.push(snapshot.with_joined_path(*new_child_ref, None)?); } } diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 9eec5f83..8f040316 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -30,6 +30,7 @@ use serde::{Deserialize, Serialize}; use crate::{ glob::Glob, + path_encoding::decode_path_name, project::DEFAULT_PROJECT_NAMES, syncback::{SyncbackReturn, SyncbackSnapshot}, }; @@ -74,13 +75,19 @@ pub fn snapshot_from_vfs( if meta.is_dir() { let (middleware, dir_name, init_path) = get_dir_middleware(vfs, path)?; + // Decode directory name if the flag is set + let decoded_name = if context.decode_windows_invalid_chars { + decode_path_name(dir_name) + } else { + dir_name.to_string() + }; // TODO: Support user defined init paths // If and when we do, make sure to go support it in // `Project::set_file_name`, as right now it special-cases // `default.project.json` as an `init` path. match middleware { - Middleware::Dir => middleware.snapshot(context, vfs, path, dir_name), - _ => middleware.snapshot(context, vfs, &init_path, dir_name), + Middleware::Dir => middleware.snapshot(context, vfs, path, &decoded_name), + _ => middleware.snapshot(context, vfs, &init_path, &decoded_name), } } else { let file_name = path @@ -152,19 +159,23 @@ fn snapshot_from_path( vfs: &Vfs, path: &Path, ) -> anyhow::Result> { + // Helper to decode name if the flag is set + let decode_name = |name: &str| -> String { + if context.decode_windows_invalid_chars { + decode_path_name(name) + } else { + name.to_string() + } + }; + if let Some(rule) = context.get_user_sync_rule(path) { - return rule - .middleware - .snapshot(context, vfs, path, rule.file_name_for_path(path)?); + let name = decode_name(rule.file_name_for_path(path)?); + return rule.middleware.snapshot(context, vfs, path, &name); } else { for rule in default_sync_rules() { if rule.matches(path) { - return rule.middleware.snapshot( - context, - vfs, - path, - rule.file_name_for_path(path)?, - ); + let name = decode_name(rule.file_name_for_path(path)?); + return rule.middleware.snapshot(context, vfs, path, &name); } } } diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap index 6356256d..cd6956c4 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap index a275a6cf..e279cf46 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap @@ -20,6 +20,7 @@ metadata: - /root/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap index 603bd2df..7bdac7ba 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap @@ -20,6 +20,7 @@ metadata: - /root/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap index f90eccc8..7c52699f 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap index 813a6767..39f6e14e 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap @@ -20,6 +20,7 @@ metadata: - /foo/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap index 2f44988d..eee0de54 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap @@ -20,6 +20,7 @@ metadata: - /foo/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ @@ -45,6 +46,7 @@ children: - /foo/Child/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: dir schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap index 0803eed1..20f3d376 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__with_metadata.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__with_metadata.snap index 7e6c260d..7b21ae9d 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__with_metadata.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__with_metadata.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap index f579d015..b72fc460 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap @@ -11,6 +11,7 @@ metadata: - /foo.model.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ @@ -26,6 +27,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap index f579d015..b72fc460 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap @@ -11,6 +11,7 @@ metadata: - /foo.model.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ @@ -26,6 +27,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap index 37fdec4e..df336a19 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap index e898dfbd..0ff2ee31 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap index a9facd2d..f026832a 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap index ae7e22db..28776eb5 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap @@ -13,6 +13,7 @@ metadata: - /bar.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap index ce577d1e..8ff184fd 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap index 9ce4624c..c2c741f7 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap index 80178738..2fac15fd 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap @@ -20,6 +20,7 @@ metadata: - /root/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap index d5f8aa9f..3a0c91af 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap @@ -20,6 +20,7 @@ metadata: - /root/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__plugin_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__plugin_module_from_vfs.snap index 91535701..cf315522 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__plugin_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__plugin_module_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: false + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap index abe11f93..807785e9 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: false + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap index 0d1ecd32..6abc6614 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: false + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap index 03ac12e5..0640328d 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: false + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap index 706b6ff5..6d15d489 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap @@ -13,6 +13,7 @@ metadata: - /bar.meta.jsonc context: emit_legacy_scripts: false + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap index 64a697d4..29321f49 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: false + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap index 1b972cf2..9ef56541 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: false + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_json.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_json.snap index 44c2123b..9e921c32 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_json.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_json.snap @@ -10,6 +10,7 @@ metadata: - /foo/bar.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_jsonc.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_jsonc.snap index 44c2123b..9e921c32 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_jsonc.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__adjacent_read_jsonc.snap @@ -10,6 +10,7 @@ metadata: - /foo/bar.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_json.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_json.snap index 6d819bfb..b8db664a 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_json.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_json.snap @@ -10,6 +10,7 @@ metadata: - /foo/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_jsonc.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_jsonc.snap index 6d819bfb..b8db664a 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_jsonc.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__meta_file__test__directory_read_jsonc.snap @@ -10,6 +10,7 @@ metadata: - /foo/init.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap index dc817e76..886e91d8 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap @@ -11,6 +11,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap index 1d739949..df1a0e7a 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap @@ -11,6 +11,7 @@ metadata: - /foo/hello.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap index 5b787c2a..8b19153f 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap @@ -12,6 +12,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: project schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap index 779afb4e..30baacd2 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap @@ -11,6 +11,7 @@ metadata: - /foo.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ @@ -31,6 +32,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap index 99432ea0..b693973b 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap @@ -12,6 +12,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: project schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap index 88f8e479..24e08067 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap @@ -12,6 +12,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: project schema: ~ @@ -32,6 +33,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap index dea385ac..544c3c7f 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap @@ -14,6 +14,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: text schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap index ae95e39b..a712765d 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap @@ -11,6 +11,7 @@ metadata: - /foo.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap index 589ef207..ea0b4016 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap @@ -11,6 +11,7 @@ metadata: - /foo.project.json context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap index ce112886..bea96770 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__with_metadata.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__with_metadata.snap index 8c8aef67..9ab9d5e3 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__with_metadata.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__with_metadata.snap @@ -13,6 +13,7 @@ metadata: - foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap index bde4798e..6f22c070 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__with_metadata.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__with_metadata.snap index a5047bc3..3ee95591 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__with_metadata.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__with_metadata.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__instance_from_vfs.snap index ef749325..d3f9ca12 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__instance_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: ~ middleware: ~ schema: ~ diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__with_metadata.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__with_metadata.snap index 8a9e1778..69209969 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__with_metadata.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__yaml__test__with_metadata.snap @@ -13,6 +13,7 @@ metadata: - foo.meta.jsonc context: emit_legacy_scripts: true + decode_windows_invalid_chars: false specified_id: manually specified middleware: ~ schema: ~ diff --git a/src/syncback/file_names.rs b/src/syncback/file_names.rs index 4653aabd..09646d7e 100644 --- a/src/syncback/file_names.rs +++ b/src/syncback/file_names.rs @@ -6,12 +6,15 @@ use std::borrow::Cow; use anyhow::Context; use rbx_dom_weak::Instance; -use crate::{snapshot::InstanceWithMeta, snapshot_middleware::Middleware}; +use crate::{ + path_encoding::encode_path_name, snapshot::InstanceWithMeta, snapshot_middleware::Middleware, +}; pub fn name_for_inst<'old>( middleware: Middleware, new_inst: &Instance, old_inst: Option>, + encode_invalid_chars: bool, ) -> anyhow::Result> { if let Some(old_inst) = old_inst { if let Some(source) = old_inst.metadata().relevant_paths.first() { @@ -35,13 +38,37 @@ pub fn name_for_inst<'old>( | Middleware::CsvDir | Middleware::ServerScriptDir | Middleware::ClientScriptDir - | Middleware::ModuleScriptDir => Cow::Owned(new_inst.name.clone()), + | Middleware::ModuleScriptDir => { + let name = if encode_invalid_chars { + let encoded = encode_path_name(&new_inst.name); + // Validate for issues not fixed by encoding (trailing space/dot, control chars, reserved names) + validate_file_name(&encoded).with_context(|| { + format!("name '{}' (encoded from '{}') is not legal to write to the file system", encoded, new_inst.name) + })?; + encoded + } else { + validate_file_name(&new_inst.name).with_context(|| { + format!("name '{}' is not legal to write to the file system", new_inst.name) + })?; + new_inst.name.clone() + }; + Cow::Owned(name) + } _ => { let extension = extension_for_middleware(middleware); - let name = &new_inst.name; - validate_file_name(name).with_context(|| { - format!("name '{name}' is not legal to write to the file system") - })?; + let name = if encode_invalid_chars { + let encoded = encode_path_name(&new_inst.name); + // Validate for issues not fixed by encoding (trailing space/dot, control chars, reserved names) + validate_file_name(&encoded).with_context(|| { + format!("name '{}' (encoded from '{}') is not legal to write to the file system", encoded, new_inst.name) + })?; + encoded + } else { + validate_file_name(&new_inst.name).with_context(|| { + format!("name '{}' is not legal to write to the file system", new_inst.name) + })?; + new_inst.name.clone() + }; Cow::Owned(format!("{name}.{extension}")) } }) diff --git a/src/syncback/mod.rs b/src/syncback/mod.rs index 4ad9d504..c42c51de 100644 --- a/src/syncback/mod.rs +++ b/src/syncback/mod.rs @@ -409,6 +409,12 @@ pub struct SyncbackRules { /// generally a better UX. #[serde(skip_serializing_if = "Option::is_none")] create_ignore_dir_paths: Option, + /// Whether to encode Windows-invalid characters in file names during + /// syncback. Characters like `<`, `>`, `:`, `"`, `/`, `\`, `|`, `?`, `*` + /// will be encoded as `%LT%`, `%GT%`, `%COLON%`, etc. + /// Defaults to `false`. + #[serde(skip_serializing_if = "Option::is_none")] + encode_windows_invalid_chars: Option, } impl SyncbackRules { @@ -432,6 +438,13 @@ impl SyncbackRules { Ok(globs) } + + /// Returns whether Windows-invalid characters should be encoded in file + /// names during syncback. Defaults to `false`. + #[inline] + pub fn encode_windows_invalid_chars(&self) -> bool { + self.encode_windows_invalid_chars.unwrap_or(false) + } } fn is_valid_path(globs: &Option>, base_path: &Path, path: &Path) -> bool { diff --git a/src/syncback/snapshot.rs b/src/syncback/snapshot.rs index 2a2f252d..77d230e6 100644 --- a/src/syncback/snapshot.rs +++ b/src/syncback/snapshot.rs @@ -44,7 +44,13 @@ impl<'sync> SyncbackSnapshot<'sync> { middleware: None, }; let middleware = get_best_middleware(&snapshot); - let name = name_for_inst(middleware, snapshot.new_inst(), snapshot.old_inst())?; + let encode_invalid_chars = self.encode_windows_invalid_chars(); + let name = name_for_inst( + middleware, + snapshot.new_inst(), + snapshot.old_inst(), + encode_invalid_chars, + )?; snapshot.path = self.path.join(name.as_ref()); Ok(snapshot) @@ -70,7 +76,13 @@ impl<'sync> SyncbackSnapshot<'sync> { middleware: None, }; let middleware = get_best_middleware(&snapshot); - let name = name_for_inst(middleware, snapshot.new_inst(), snapshot.old_inst())?; + let encode_invalid_chars = self.encode_windows_invalid_chars(); + let name = name_for_inst( + middleware, + snapshot.new_inst(), + snapshot.old_inst(), + encode_invalid_chars, + )?; snapshot.path = base_path.join(name.as_ref()); Ok(snapshot) @@ -224,6 +236,34 @@ impl<'sync> SyncbackSnapshot<'sync> { .map(|classes| classes.iter().any(|c| c == class_name)) .unwrap_or(false) } + + /// Checks if an instance should be ignored based on ignoreTrees rules. + /// Takes a Ref to check against the new tree's instance path. + #[inline] + pub fn should_ignore_tree(&self, referent: Ref) -> bool { + if let Some(ignore_trees) = self.ignore_tree() { + let path = inst_path(self.new_tree(), referent); + for ignored in ignore_trees { + if path.starts_with(ignored.as_str()) { + log::debug!("Ignoring {path} because it matches ignoreTrees entry: {ignored}"); + return true; + } + } + } + false + } + + /// Returns whether Windows-invalid characters should be encoded in file + /// names during syncback. + #[inline] + pub fn encode_windows_invalid_chars(&self) -> bool { + self.data + .project + .syncback_rules + .as_ref() + .map(|rules| rules.encode_windows_invalid_chars()) + .unwrap_or(false) + } } pub fn filter_out_property(inst: &Instance, prop_name: &str) -> bool {