Skip to content

Commit 3c925dc

Browse files
committed
fix Configuration directory environment variable loading
fixes #598 also adds extensive tests to prevent this from happening again
1 parent dde5d0d commit 3c925dc

File tree

1 file changed

+146
-9
lines changed

1 file changed

+146
-9
lines changed

src/app_config.rs

Lines changed: 146 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ impl AppConfig {
4646
config.configuration_directory.clone_from(config_dir);
4747
}
4848

49-
config.configuration_directory =
50-
cli.config_dir.clone().unwrap_or(PathBuf::from("./sqlpage"));
49+
if let Some(config_dir) = &cli.config_dir {
50+
config.configuration_directory.clone_from(config_dir);
51+
}
5152

5253
config.configuration_directory = std::fs::canonicalize(&config.configuration_directory)
5354
.unwrap_or_else(|_| config.configuration_directory.clone());
@@ -65,6 +66,9 @@ impl AppConfig {
6566
}
6667

6768
config.validate()?;
69+
70+
log::debug!("Loaded configuration: {:#?}", config);
71+
6872
Ok(config)
6973
}
7074

@@ -282,7 +286,6 @@ pub fn load_from_file(config_file: &Path) -> anyhow::Result<AppConfig> {
282286
let app_config = config
283287
.try_deserialize::<AppConfig>()
284288
.with_context(|| "Unable to load configuration")?;
285-
log::debug!("Loaded configuration: {:#?}", app_config);
286289
Ok(app_config)
287290
}
288291

@@ -479,6 +482,10 @@ pub mod tests {
479482
#[cfg(test)]
480483
mod test {
481484
use super::*;
485+
use std::env;
486+
use std::sync::Mutex;
487+
488+
static ENV_LOCK: Mutex<()> = Mutex::new(());
482489

483490
#[test]
484491
fn test_default_site_prefix() {
@@ -510,21 +517,151 @@ mod test {
510517
}
511518

512519
#[test]
513-
fn test_cli() {
520+
fn test_cli_argument_parsing() {
514521
let cli = Cli::parse_from(&[
515522
"sqlpage",
516523
"--web-root",
517524
"/path/to/web",
518525
"--config-dir",
519-
"custom_config",
526+
"/path/to/config",
527+
"--config-file",
528+
"/path/to/config.json",
520529
]);
530+
521531
assert_eq!(cli.web_root, Some(PathBuf::from("/path/to/web")));
522-
assert_eq!(cli.config_dir, Some(PathBuf::from("custom_config")));
532+
assert_eq!(cli.config_dir, Some(PathBuf::from("/path/to/config")));
533+
assert_eq!(cli.config_file, Some(PathBuf::from("/path/to/config.json")));
534+
}
535+
536+
#[test]
537+
fn test_sqlpage_prefixed_env_variable_parsing() {
538+
let _lock = ENV_LOCK
539+
.lock()
540+
.expect("Another test panicked while holding the lock");
541+
env::set_var("SQLPAGE_CONFIGURATION_DIRECTORY", "/path/to/config");
542+
543+
let config = load_from_env().unwrap();
544+
545+
assert_eq!(
546+
config.configuration_directory,
547+
PathBuf::from("/path/to/config"),
548+
"Configuration directory should match the SQLPAGE_CONFIGURATION_DIRECTORY env var"
549+
);
550+
551+
env::remove_var("SQLPAGE_CONFIGURATION_DIRECTORY");
552+
}
553+
554+
#[test]
555+
fn test_config_priority() {
556+
let _lock = ENV_LOCK
557+
.lock()
558+
.expect("Another test panicked while holding the lock");
559+
env::set_var("SQLPAGE_WEB_ROOT", "/");
560+
561+
let cli = Cli {
562+
web_root: Some(PathBuf::from(".")),
563+
config_dir: None,
564+
config_file: None,
565+
};
566+
567+
let config = AppConfig::from_cli(&cli).unwrap();
568+
569+
assert_eq!(
570+
config.web_root,
571+
PathBuf::from("."),
572+
"CLI argument should take precedence over environment variable"
573+
);
574+
575+
env::remove_var("SQLPAGE_WEB_ROOT");
576+
}
577+
578+
#[test]
579+
fn test_config_file_priority() {
580+
let _lock = ENV_LOCK
581+
.lock()
582+
.expect("Another test panicked while holding the lock");
583+
let temp_dir = std::env::temp_dir().join("sqlpage_test");
584+
std::fs::create_dir_all(&temp_dir).unwrap();
585+
let config_file_path = temp_dir.join("sqlpage.json");
586+
let config_web_dir = temp_dir.join("config/web");
587+
let env_web_dir = temp_dir.join("env/web");
588+
let cli_web_dir = temp_dir.join("cli/web");
589+
std::fs::create_dir_all(&config_web_dir).unwrap();
590+
std::fs::create_dir_all(&env_web_dir).unwrap();
591+
std::fs::create_dir_all(&cli_web_dir).unwrap();
592+
593+
let config_content = format!(
594+
r#"{{ "web_root": "{}" }}"#,
595+
config_web_dir.to_str().unwrap()
596+
);
597+
std::fs::write(&config_file_path, config_content).unwrap();
598+
599+
env::set_var("SQLPAGE_WEB_ROOT", env_web_dir.to_str().unwrap());
600+
601+
let cli = Cli {
602+
web_root: None,
603+
config_dir: None,
604+
config_file: Some(config_file_path.clone()),
605+
};
606+
607+
let config = AppConfig::from_cli(&cli).unwrap();
608+
609+
assert_eq!(
610+
config.web_root, env_web_dir,
611+
"Environment variable should override config file"
612+
);
613+
assert_eq!(
614+
config.configuration_directory,
615+
cannonicalize_if_possible(&PathBuf::from("./sqlpage")),
616+
"Configuration directory should be default when not overridden"
617+
);
618+
619+
let cli_with_web_root = Cli {
620+
web_root: Some(cli_web_dir.clone()),
621+
config_dir: None,
622+
config_file: Some(config_file_path),
623+
};
624+
625+
let config = AppConfig::from_cli(&cli_with_web_root).unwrap();
626+
assert_eq!(
627+
config.web_root, cli_web_dir,
628+
"CLI argument should take precedence over environment variable and config file"
629+
);
630+
assert_eq!(
631+
config.configuration_directory,
632+
cannonicalize_if_possible(&PathBuf::from("./sqlpage")),
633+
"Configuration directory should remain unchanged"
634+
);
635+
636+
env::remove_var("SQLPAGE_WEB_ROOT");
637+
std::fs::remove_dir_all(&temp_dir).unwrap();
523638
}
524639

525640
#[test]
526-
fn verify_cli() {
527-
use clap::CommandFactory;
528-
Cli::command().debug_assert();
641+
fn test_default_values() {
642+
let _lock = ENV_LOCK
643+
.lock()
644+
.expect("Another test panicked while holding the lock");
645+
env::remove_var("SQLPAGE_CONFIGURATION_DIRECTORY");
646+
env::remove_var("SQLPAGE_WEB_ROOT");
647+
648+
let cli = Cli {
649+
web_root: None,
650+
config_dir: None,
651+
config_file: None,
652+
};
653+
654+
let config = AppConfig::from_cli(&cli).unwrap();
655+
656+
assert_eq!(
657+
config.web_root,
658+
default_web_root(),
659+
"Web root should default to current directory when not specified"
660+
);
661+
assert_eq!(
662+
config.configuration_directory,
663+
cannonicalize_if_possible(&PathBuf::from("./sqlpage")),
664+
"Configuration directory should default to ./sqlpage when not specified"
665+
);
529666
}
530667
}

0 commit comments

Comments
 (0)