From 12b8701e00adcf8d2d409e5f98c374fc64b8a1ec Mon Sep 17 00:00:00 2001 From: mace Date: Thu, 17 Sep 2026 10:43:13 +0200 Subject: [PATCH] support RCC_-prefixed env keys alongside legacy dotted keys connections.env and local .env are transitioning from dotted keys (ci.db.master.ip, connection) to upper-cased RCC_-prefixed keys (RCC_CI_DB_MASTER_IP, RCC_CONNECTION). Both forms are matched and toggled during the migration, so old branches keep working while new ones use the new format. --- src/config/parse.rs | 106 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 9 deletions(-) diff --git a/src/config/parse.rs b/src/config/parse.rs index 56472f9..96d87fc 100644 --- a/src/config/parse.rs +++ b/src/config/parse.rs @@ -44,12 +44,40 @@ pub fn set_dot_env(start: bool, config: &DevToolsConf) -> Result<()> { Ok(()) } +const CI_DB_MASTER_IP: &str = "ci.db.master.ip"; +const CI_DB_MASTER_PORT: &str = "ci.db.master.port"; +const CONNECTION: &str = "connection"; + +const RCC_CI_DB_MASTER_IP: &str = "RCC_CI_DB_MASTER_IP"; +const RCC_CI_DB_MASTER_PORT: &str = "RCC_CI_DB_MASTER_PORT"; +const RCC_CONNECTION: &str = "RCC_CONNECTION"; + +/// Converts a legacy dotted key (`ci.db.master.ip`) into its `RCC_`-prefixed +/// replacement (`RCC_CI_DB_MASTER_IP`), as used by the new env file format. +/// Test-only: keeps the `RCC_*` consts above honest (see `rcc_key_matches_const`) +/// — the hot paths below use the consts directly to avoid allocating per line. +#[cfg(test)] +fn rcc_key(dotted_key: &str) -> String { + format!("RCC_{}", dotted_key.to_uppercase().replace('.', "_")) +} + +fn starts_with_env_key(line: &str, key: &str) -> bool { + line.strip_prefix(key) + .is_some_and(|rest| rest.starts_with('=')) +} + pub(crate) fn connections_env_comment(line: &str) -> bool { - line.starts_with("ci.db.master.ip=") || line.starts_with("ci.db.master.port=") + starts_with_env_key(line, CI_DB_MASTER_IP) + || starts_with_env_key(line, RCC_CI_DB_MASTER_IP) + || starts_with_env_key(line, CI_DB_MASTER_PORT) + || starts_with_env_key(line, RCC_CI_DB_MASTER_PORT) } pub(crate) fn should_commented_out(line: &str) -> bool { - line.starts_with("# ci.db.master.ip=") || line.starts_with("# ci.db.master.port=") + match line.strip_prefix("# ") { + Some(rest) => connections_env_comment(rest), + None => false, + } } fn toggle_after_line( @@ -86,14 +114,10 @@ fn toggle_after_line( if relevant { modified_lines.push(toggle(&line_content, activate)); counter += 1; + } else if let Some(key) = connection_key(&line_content) { + let value = if activate { "staging" } else { "ci" }; + modified_lines.push(format!("{}='{}'", key, value)); } else { - if !activate && line_content.trim_start().starts_with("connection=") { - modified_lines.push("connection='ci'".to_string()); - continue; - } else if activate && line_content.trim_start().starts_with("connection=") { - modified_lines.push("connection='staging'".to_string()); - continue; - } modified_lines.push(line_content); } } @@ -104,6 +128,19 @@ fn toggle_after_line( Ok(()) } +/// Returns the `connection` key as it appears on the given line (either the +/// legacy `connection` or the new `RCC_CONNECTION`), if the line sets it. +fn connection_key(line: &str) -> Option<&'static str> { + let trimmed = line.trim_start(); + if starts_with_env_key(trimmed, CONNECTION) { + Some(CONNECTION) + } else if starts_with_env_key(trimmed, RCC_CONNECTION) { + Some(RCC_CONNECTION) + } else { + None + } +} + pub(crate) fn toggle(line: &str, activate: bool) -> String { if activate { return line.replacen('#', "", 1); @@ -169,4 +206,55 @@ mod tests { fn should_commented_out_ignores_uncommented() { assert!(!should_commented_out("ci.db.master.ip=127.0.0.1")); } + + #[test] + fn rcc_key_converts_dotted_key() { + assert_eq!(rcc_key("ci.db.master.ip"), "RCC_CI_DB_MASTER_IP"); + assert_eq!(rcc_key("connection"), "RCC_CONNECTION"); + } + + #[test] + fn rcc_key_matches_const() { + assert_eq!(rcc_key(CI_DB_MASTER_IP), RCC_CI_DB_MASTER_IP); + assert_eq!(rcc_key(CI_DB_MASTER_PORT), RCC_CI_DB_MASTER_PORT); + assert_eq!(rcc_key(CONNECTION), RCC_CONNECTION); + } + + #[test] + fn connections_env_comment_matches_rcc_ip() { + assert!(connections_env_comment("RCC_CI_DB_MASTER_IP=127.0.0.1")); + } + + #[test] + fn connections_env_comment_matches_rcc_port() { + assert!(connections_env_comment("RCC_CI_DB_MASTER_PORT=5432")); + } + + #[test] + fn should_commented_out_matches_rcc_ip() { + assert!(should_commented_out("# RCC_CI_DB_MASTER_IP=127.0.0.1")); + } + + #[test] + fn should_commented_out_matches_rcc_port() { + assert!(should_commented_out("# RCC_CI_DB_MASTER_PORT=5432")); + } + + #[test] + fn connection_key_matches_legacy() { + assert_eq!(connection_key("connection='ci'"), Some("connection")); + } + + #[test] + fn connection_key_matches_rcc() { + assert_eq!( + connection_key("RCC_CONNECTION='ci'"), + Some("RCC_CONNECTION") + ); + } + + #[test] + fn connection_key_ignores_other() { + assert_eq!(connection_key("connection_pool=5"), None); + } }