From 38c5e28eab860d96d0ffb7528b01b66295e2411d Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 11 May 2026 22:41:46 +0000 Subject: [PATCH 1/2] feat(server): add config file override flag --- aw-server/src/config.rs | 58 ++++++++++++++++++++++++++++++++++++++--- aw-server/src/main.rs | 6 ++++- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/aw-server/src/config.rs b/aw-server/src/config.rs index 37d59bbd..a90aa513 100644 --- a/aw-server/src/config.rs +++ b/aw-server/src/config.rs @@ -1,5 +1,6 @@ -use std::fs::File; +use std::fs::{self, File}; use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; use rocket::config::Config; use rocket::data::{Limits, ToByteUnit}; @@ -119,8 +120,11 @@ fn default_custom_static() -> std::collections::HashMap { std::collections::HashMap::new() } -pub fn create_config(testing: bool) -> AWConfig { - set_testing(testing); +fn get_config_path(testing: bool, config_override: Option<&Path>) -> PathBuf { + if let Some(config_path) = config_override { + return config_path.to_path_buf(); + } + let mut config_path = dirs::get_config_dir().unwrap(); if !testing { config_path.push("config.toml") @@ -128,6 +132,16 @@ pub fn create_config(testing: bool) -> AWConfig { config_path.push("config-testing.toml") } + config_path +} + +pub fn create_config(testing: bool, config_override: Option<&Path>) -> AWConfig { + set_testing(testing); + let config_path = get_config_path(testing, config_override); + if let Some(parent) = config_path.parent() { + fs::create_dir_all(parent).expect("Unable to create config dir"); + } + /* If there is no config file, create a new config file with default values but every value is * commented out by default in case we would change a default value at some point in the future */ if !config_path.is_file() { @@ -157,3 +171,41 @@ pub fn create_config(testing: bool) -> AWConfig { aw_config } + +#[cfg(test)] +mod tests { + use super::create_config; + use std::fs; + use std::path::PathBuf; + use uuid::Uuid; + + fn unique_test_path(name: &str) -> PathBuf { + std::env::temp_dir() + .join("aw-server-config-tests") + .join(format!("{name}-{}", Uuid::new_v4())) + .join("config.toml") + } + + #[test] + fn create_config_uses_override_path() { + let config_path = unique_test_path("override"); + fs::create_dir_all(config_path.parent().unwrap()).unwrap(); + fs::write(&config_path, "address = \"0.0.0.0\"\nport = 5611\n").unwrap(); + + let config = create_config(false, Some(config_path.as_path())); + + assert_eq!(config.address, "0.0.0.0"); + assert_eq!(config.port, 5611); + } + + #[test] + fn create_config_creates_missing_override_file() { + let config_path = unique_test_path("missing"); + + let config = create_config(false, Some(config_path.as_path())); + + assert!(config_path.is_file()); + assert_eq!(config.address, "127.0.0.1"); + assert_eq!(config.port, 5600); + } +} diff --git a/aw-server/src/main.rs b/aw-server/src/main.rs index 2cbf39e7..1d883d9b 100644 --- a/aw-server/src/main.rs +++ b/aw-server/src/main.rs @@ -42,6 +42,10 @@ struct Opts { #[clap(long)] dbpath: Option, + /// Path to config file override + #[clap(short = 'c', long = "config")] + config: Option, + /// Path to webui override #[clap(long)] webpath: Option, @@ -79,7 +83,7 @@ async fn main() -> Result<(), rocket::Error> { info!("Running server in Testing mode"); } - let mut config = config::create_config(testing); + let mut config = config::create_config(testing, opts.config.as_deref()); // set host if overridden if let Some(host) = opts.host { From 3c8270bab319461e132d3a1d010fdf665b879038 Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 11 May 2026 23:04:32 +0000 Subject: [PATCH 2/2] test(server): isolate config override tests --- aw-server/src/config.rs | 45 ++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/aw-server/src/config.rs b/aw-server/src/config.rs index a90aa513..6e09bf42 100644 --- a/aw-server/src/config.rs +++ b/aw-server/src/config.rs @@ -177,22 +177,42 @@ mod tests { use super::create_config; use std::fs; use std::path::PathBuf; + use std::sync::Mutex; use uuid::Uuid; - fn unique_test_path(name: &str) -> PathBuf { - std::env::temp_dir() - .join("aw-server-config-tests") - .join(format!("{name}-{}", Uuid::new_v4())) - .join("config.toml") + static TEST_LOCK: Mutex<()> = Mutex::new(()); + + struct TestConfigPath { + root: PathBuf, + config_path: PathBuf, + } + + impl TestConfigPath { + fn new(name: &str) -> Self { + let root = std::env::temp_dir() + .join("aw-server-config-tests") + .join(format!("{name}-{}", Uuid::new_v4())); + let config_path = root.join("config.toml"); + + Self { root, config_path } + } + } + + impl Drop for TestConfigPath { + fn drop(&mut self) { + let _ = fs::remove_dir_all(&self.root); + } } #[test] fn create_config_uses_override_path() { - let config_path = unique_test_path("override"); - fs::create_dir_all(config_path.parent().unwrap()).unwrap(); - fs::write(&config_path, "address = \"0.0.0.0\"\nport = 5611\n").unwrap(); + // create_config mutates the TESTING global, so these tests must not overlap. + let _lock = TEST_LOCK.lock().unwrap(); + let paths = TestConfigPath::new("override"); + fs::create_dir_all(paths.config_path.parent().unwrap()).unwrap(); + fs::write(&paths.config_path, "address = \"0.0.0.0\"\nport = 5611\n").unwrap(); - let config = create_config(false, Some(config_path.as_path())); + let config = create_config(false, Some(paths.config_path.as_path())); assert_eq!(config.address, "0.0.0.0"); assert_eq!(config.port, 5611); @@ -200,11 +220,12 @@ mod tests { #[test] fn create_config_creates_missing_override_file() { - let config_path = unique_test_path("missing"); + let _lock = TEST_LOCK.lock().unwrap(); + let paths = TestConfigPath::new("missing"); - let config = create_config(false, Some(config_path.as_path())); + let config = create_config(false, Some(paths.config_path.as_path())); - assert!(config_path.is_file()); + assert!(paths.config_path.is_file()); assert_eq!(config.address, "127.0.0.1"); assert_eq!(config.port, 5600); }