From d6503d5101169440a7145c52bc881adbd1fe9b8d Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Wed, 12 Mar 2025 07:59:29 +0000 Subject: [PATCH] Fix a few more translation bugs --- src/game.rs | 8 +++- src/metadata/metadata_document.rs | 77 ++++++++++++++++++++++++++++--- src/plugin/mod.rs | 7 ++- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/game.rs b/src/game.rs index 67b498d1..bb9549e3 100644 --- a/src/game.rs +++ b/src/game.rs @@ -300,7 +300,12 @@ impl Game { /// relative to the game's plugins directory, while absolute paths are used /// as given. pub fn is_valid_plugin(&self, plugin_path: &Path) -> bool { - validate_plugin_path_and_header(self.game_type, plugin_path).is_ok() + let resolved_path = resolve_plugin_path( + self.game_type, + &data_path(self.game_type, &self.game_path), + plugin_path, + ); + validate_plugin_path_and_header(self.game_type, &resolved_path).is_ok() } /// Fully parses plugins and loads their data. @@ -527,6 +532,7 @@ impl Game { /// of active plugins is unchanged. pub fn set_load_order(&mut self, load_order: &[&str]) -> Result<(), LoadOrderError> { self.load_order.set_load_order(load_order)?; + self.load_order.save()?; Ok(()) } } diff --git a/src/metadata/metadata_document.rs b/src/metadata/metadata_document.rs index cc816c9f..a042646b 100644 --- a/src/metadata/metadata_document.rs +++ b/src/metadata/metadata_document.rs @@ -222,7 +222,7 @@ impl MetadataDocument { emitter.end_array(); } - if !self.groups.is_empty() { + if self.groups.len() > 1 { emitter.map_key("groups"); self.groups.emit_yaml(&mut emitter); } @@ -238,13 +238,20 @@ impl MetadataDocument { emitter.begin_array(); for plugin in self.plugins() { - plugin.emit_yaml(&mut emitter); + if !plugin.has_name_only() { + plugin.emit_yaml(&mut emitter); + } } emitter.end_array(); } - std::fs::write(file_path, emitter.into_string()) + let mut contents = emitter.into_string(); + if contents.is_empty() { + contents = "{}".into(); + } + + std::fs::write(file_path, contents) .map_err(|e| WriteMetadataError::new(file_path.into(), e.into()))?; Ok(()) @@ -397,8 +404,9 @@ fn merge_hashes( } fn replace_prelude(masterlist: String, prelude: String) -> String { + let line_ending = detect_line_ending(&masterlist); if let Some((start, end)) = find_prelude_bounds(&masterlist) { - let prelude = indent_prelude(prelude); + let prelude = indent_prelude(prelude, line_ending); masterlist[..start].to_string() + &prelude + &masterlist[end..] } else { @@ -406,6 +414,20 @@ fn replace_prelude(masterlist: String, prelude: String) -> String { } } +fn detect_line_ending(masterlist: &str) -> &'static str { + if let Some(pos) = masterlist.rfind("\n") { + if pos == 0 { + "\n" + } else if masterlist.as_bytes()[pos - 1] == b'\r' { + "\r\n" + } else { + "\n" + } + } else { + "\n" + } +} + fn find_prelude_bounds(masterlist: &str) -> Option<(usize, usize)> { let prelude_on_first_line = "prelude:"; let prelude_on_new_line = "\nprelude:"; @@ -428,7 +450,7 @@ fn find_prelude_bounds(masterlist: &str) -> Option<(usize, usize)> { if let Some(c) = masterlist.as_bytes().get(pos) { if *c != b' ' && *c != b'#' && *c != b'\n' { - return Some((start, next_line_break_pos)); + return Some((start, pos - 1)); } } } @@ -436,8 +458,9 @@ fn find_prelude_bounds(masterlist: &str) -> Option<(usize, usize)> { Some((start, masterlist.len())) } -fn indent_prelude(prelude: String) -> String { - let prelude = ("\n ".to_string() + &prelude.replace("\n", "\n ")).replace(" \n", "\n"); +fn indent_prelude(prelude: String, line_ending: &str) -> String { + let prelude = ("\n ".to_string() + &prelude.replace("\n", "\n ")) + .replace(&format!(" {}", line_ending), line_ending); if prelude.ends_with("\n ") { prelude[..prelude.len() - 2].to_string() @@ -545,6 +568,46 @@ plugins: metadata_list.load(&path).unwrap(); } + #[test] + fn load_with_prelude_should_merge_docs_with_crlf_line_endings() { + let tmp_dir = tempdir().unwrap(); + + let masterlist_path = tmp_dir.path().join("masterlist.yaml"); + std::fs::write(&masterlist_path, "prelude:\r\n - &ref\r\n type: say\r\n content: Loaded from same file\r\nglobals:\r\n - *ref\r\n").unwrap(); + + let prelude_path = tmp_dir.path().join("prelude.yaml"); + std::fs::write( + &prelude_path, + "common:\r\n - &ref\r\n type: say\r\n content: Loaded from prelude\r\n", + ) + .unwrap(); + + let mut metadata_list = MetadataDocument::default(); + metadata_list + .load_with_prelude(&masterlist_path, &prelude_path) + .unwrap(); + } + + #[test] + fn load_with_prelude_should_merge_docs_with_lf_line_endings() { + let tmp_dir = tempdir().unwrap(); + + let masterlist_path = tmp_dir.path().join("masterlist.yaml"); + std::fs::write(&masterlist_path, "prelude:\n - &ref\n type: say\n content: Loaded from same file\nglobals:\n - *ref\n").unwrap(); + + let prelude_path = tmp_dir.path().join("prelude.yaml"); + std::fs::write( + &prelude_path, + "common:\n - &ref\n type: say\n content: Loaded from prelude\n", + ) + .unwrap(); + + let mut metadata_list = MetadataDocument::default(); + metadata_list + .load_with_prelude(&masterlist_path, &prelude_path) + .unwrap(); + } + #[test] fn save_should_write_the_loaded_metadata() { let tmp_dir = tempdir().unwrap(); diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs index 0955a3e4..4a7edd0c 100644 --- a/src/plugin/mod.rs +++ b/src/plugin/mod.rs @@ -16,7 +16,9 @@ use crate::{ GameType, archive::{assets_in_archives, find_associated_archives}, game::GameCache, - logging, regex, + logging, + metadata::plugin_metadata::trim_dot_ghost, + regex, }; use error::{ InvalidFilenameReason, LoadPluginError, PluginDataError, PluginValidationError, @@ -409,7 +411,7 @@ pub(crate) fn plugins_metadata( fn name_string(path: &Path) -> Result { match path.file_name() { Some(f) => match f.to_str() { - Some(f) => Ok(f.to_string()), + Some(f) => Ok(trim_dot_ghost(f).to_string()), None => Err(LoadPluginError::InvalidFilename( InvalidFilenameReason::NonUnicode, )), @@ -460,6 +462,7 @@ fn extract_version(description: &str) -> Result, Box