diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/integration/config_edit.rs | 69 | ||||
| -rw-r--r-- | src/integration/tests.rs | 77 |
2 files changed, 132 insertions, 14 deletions
diff --git a/src/integration/config_edit.rs b/src/integration/config_edit.rs index 630682ce..812907e7 100644 --- a/src/integration/config_edit.rs +++ b/src/integration/config_edit.rs @@ -428,12 +428,24 @@ pub(crate) fn update_hermes_enabled_plugin(content: &str, enabled: bool) -> Stri .map(|offset| plugins_index + 1 + offset); if let Some(enabled_index) = enabled_index { - let line = lines[enabled_index].trim(); - if line == "enabled: []" || line == "enabled: [] # herdr" { - if enabled { - lines[enabled_index] = " enabled:".to_string(); - lines.insert(enabled_index + 1, " - herdr-agent-state".to_string()); + if let Some(mut items) = yaml_key_value_at_indent(&lines[enabled_index], 2, "enabled") + .and_then(yaml_flow_sequence_items) + { + let existing_item_index = items + .iter() + .position(|item| yaml_scalar_value(item) == HERMES_PLUGIN_INSTALL_NAME); + + match (enabled, existing_item_index) { + (true, Some(_)) | (false, None) => return content.to_string(), + (true, None) => items.insert(0, HERMES_PLUGIN_INSTALL_NAME.to_string()), + (false, Some(index)) => { + items.remove(index); + } } + + let comment = yaml_inline_comment(&lines[enabled_index]); + let replacement = hermes_enabled_plugin_lines(&items, comment); + lines.splice(enabled_index..enabled_index + 1, replacement); return join_yaml_lines(lines, trailing_newline); } @@ -463,7 +475,7 @@ pub(crate) fn update_hermes_enabled_plugin(content: &str, enabled: bool) -> Stri if let Some(mut items) = plugins_inline_items { let existing_item_index = items .iter() - .position(|item| item == HERMES_PLUGIN_INSTALL_NAME); + .position(|item| yaml_scalar_value(item) == HERMES_PLUGIN_INSTALL_NAME); match (enabled, existing_item_index) { (true, Some(_)) | (false, None) => return content.to_string(), @@ -473,7 +485,8 @@ pub(crate) fn update_hermes_enabled_plugin(content: &str, enabled: bool) -> Stri } } - let replacement = hermes_flat_plugin_lines(&items); + let comment = yaml_inline_comment(&lines[plugins_index]); + let replacement = hermes_flat_plugin_lines(&items, comment); lines.splice(plugins_index..plugins_end, replacement); return join_yaml_lines(lines, trailing_newline); } @@ -503,16 +516,37 @@ pub(crate) fn update_hermes_enabled_plugin(content: &str, enabled: bool) -> Stri content.to_string() } -pub(crate) fn hermes_flat_plugin_lines(items: &[String]) -> Vec<String> { +pub(crate) fn hermes_flat_plugin_lines(items: &[String], comment: Option<&str>) -> Vec<String> { if items.is_empty() { - return vec!["plugins: []".to_string()]; + return vec![with_yaml_inline_comment("plugins: []".to_string(), comment)]; } - let mut lines = vec!["plugins:".to_string()]; + let mut lines = vec![with_yaml_inline_comment("plugins:".to_string(), comment)]; lines.extend(items.iter().map(|item| format!(" - {item}"))); lines } +pub(crate) fn hermes_enabled_plugin_lines(items: &[String], comment: Option<&str>) -> Vec<String> { + if items.is_empty() { + return vec![with_yaml_inline_comment( + " enabled: []".to_string(), + comment, + )]; + } + + let mut lines = vec![with_yaml_inline_comment(" enabled:".to_string(), comment)]; + lines.extend(items.iter().map(|item| format!(" - {item}"))); + lines +} + +fn with_yaml_inline_comment(mut line: String, comment: Option<&str>) -> String { + if let Some(comment) = comment { + line.push(' '); + line.push_str(comment.trim_end()); + } + line +} + pub(crate) fn top_level_yaml_key_index(lines: &[String], key: &str) -> Option<usize> { lines .iter() @@ -619,7 +653,7 @@ pub(crate) fn yaml_flow_sequence_items(value: &str) -> Option<Vec<String>> { current.push(ch); } ',' => { - items.push(yaml_scalar_value(¤t)); + items.push(current.trim().to_string()); current.clear(); } _ => current.push(ch), @@ -630,7 +664,7 @@ pub(crate) fn yaml_flow_sequence_items(value: &str) -> Option<Vec<String>> { return None; } - items.push(yaml_scalar_value(¤t)); + items.push(current.trim().to_string()); Some(items) } @@ -648,6 +682,13 @@ pub(crate) fn yaml_scalar_value(value: &str) -> String { } pub(crate) fn strip_yaml_inline_comment(value: &str) -> &str { + match yaml_inline_comment(value) { + Some(comment) => value[..value.len() - comment.len()].trim_end(), + None => value, + } +} + +pub(crate) fn yaml_inline_comment(value: &str) -> Option<&str> { let mut quote = None; let mut escaped = false; @@ -667,13 +708,13 @@ pub(crate) fn strip_yaml_inline_comment(value: &str) -> &str { match ch { '"' | '\'' => quote = Some(ch), '#' if index == 0 || value[..index].ends_with(char::is_whitespace) => { - return value[..index].trim_end(); + return Some(&value[index..]); } _ => {} } } - value + None } pub(crate) fn join_yaml_lines(lines: Vec<String>, trailing_newline: bool) -> String { diff --git a/src/integration/tests.rs b/src/integration/tests.rs index 41a4e027..eb310637 100644 --- a/src/integration/tests.rs +++ b/src/integration/tests.rs @@ -2704,6 +2704,59 @@ fn install_hermes_converts_flow_plugin_list_to_block_list() { } #[test] +fn install_hermes_converts_inline_enabled_list_to_block_list() { + let config = update_hermes_enabled_plugin("plugins:\n enabled: [example-plugin]\n", true); + assert_eq!( + config, + "plugins:\n enabled:\n - herdr-agent-state\n - example-plugin\n" + ); +} + +#[test] +fn install_hermes_preserves_quoted_inline_enabled_items() { + let config = + update_hermes_enabled_plugin("plugins:\n enabled: [\"null\", 'foo: bar']\n", true); + assert_eq!( + config, + "plugins:\n enabled:\n - herdr-agent-state\n - \"null\"\n - 'foo: bar'\n" + ); +} + +#[test] +fn install_hermes_preserves_inline_enabled_comment() { + let config = update_hermes_enabled_plugin( + "plugins:\n enabled: [example-plugin] # managed locally\n", + true, + ); + assert_eq!( + config, + "plugins:\n enabled: # managed locally\n - herdr-agent-state\n - example-plugin\n" + ); +} + +#[test] +fn install_hermes_preserves_inline_plugins_comment() { + let config = + update_hermes_enabled_plugin("plugins: [platforms/discord] # managed locally\n", true); + assert_eq!( + config, + "plugins: # managed locally\n - herdr-agent-state\n - platforms/discord\n" + ); +} + +#[test] +fn install_hermes_is_idempotent_for_inline_enabled_list_entry() { + let config = update_hermes_enabled_plugin( + "plugins:\n enabled: [herdr-agent-state, example-plugin]\n", + true, + ); + assert_eq!( + config, + "plugins:\n enabled: [herdr-agent-state, example-plugin]\n" + ); +} + +#[test] fn install_hermes_is_idempotent_for_quoted_flat_plugin_entry() { let _lock = integration_env_lock(); let base = unique_base(); @@ -2825,6 +2878,30 @@ fn uninstall_hermes_removes_flow_plugin_list_entry() { } #[test] +fn uninstall_hermes_removes_inline_enabled_list_entry() { + let config = update_hermes_enabled_plugin( + "plugins:\n enabled: [example-plugin, herdr-agent-state]\n", + false, + ); + assert_eq!(config, "plugins:\n enabled:\n - example-plugin\n"); +} + +#[test] +fn uninstall_hermes_preserves_quoted_inline_enabled_items() { + let config = update_hermes_enabled_plugin( + "plugins:\n enabled: ['foo: bar', herdr-agent-state]\n", + false, + ); + assert_eq!(config, "plugins:\n enabled:\n - 'foo: bar'\n"); +} + +#[test] +fn uninstall_hermes_converts_single_inline_enabled_entry_to_empty_list() { + let config = update_hermes_enabled_plugin("plugins:\n enabled: [herdr-agent-state]\n", false); + assert_eq!(config, "plugins:\n enabled: []\n"); +} + +#[test] fn uninstall_hermes_removes_commented_flat_plugin_entry() { let _lock = integration_env_lock(); let base = unique_base(); |
