use super::Config;
use crate::types::StorageMode;
use std::path::Path;
pub struct StorageModeHandler;
impl StorageModeHandler {
pub fn load_for_mode(
mode: StorageMode,
global_path: Option<&Path>,
project_path: Option<&Path>,
) -> crate::error::StorageResult<Config> {
match mode {
StorageMode::GlobalOnly => Self::load_global_only(global_path),
StorageMode::ProjectOnly => Self::load_project_only(project_path),
StorageMode::Merged => Self::load_merged(global_path, project_path),
}
}
fn load_global_only(global_path: Option<&Path>) -> crate::error::StorageResult<Config> {
if let Some(path) = global_path {
let config_file = path.join("config.yaml");
if config_file.exists() {
return super::loader::ConfigLoader::load_from_file(&config_file);
}
}
Ok(Config::default())
}
fn load_project_only(project_path: Option<&Path>) -> crate::error::StorageResult<Config> {
if let Some(path) = project_path {
let config_file = path.join("config.yaml");
if config_file.exists() {
return super::loader::ConfigLoader::load_from_file(&config_file);
}
}
Ok(Config::default())
}
fn load_merged(
global_path: Option<&Path>,
project_path: Option<&Path>,
) -> crate::error::StorageResult<Config> {
let global_config = if let Some(path) = global_path {
let config_file = path.join("config.yaml");
if config_file.exists() {
super::loader::ConfigLoader::load_from_file(&config_file).ok()
} else {
None
}
} else {
None
};
let project_config = if let Some(path) = project_path {
let config_file = path.join("config.yaml");
if config_file.exists() {
super::loader::ConfigLoader::load_from_file(&config_file).ok()
} else {
None
}
} else {
None
};
let (merged, _) = super::merge::ConfigMerger::merge(
Config::default(),
global_config,
project_config,
None,
);
Ok(merged)
}
pub fn verify_isolation(
mode: StorageMode,
global_path: Option<&Path>,
project_path: Option<&Path>,
) -> crate::error::StorageResult<bool> {
match mode {
StorageMode::GlobalOnly => {
if let Some(path) = project_path {
let config_file = path.join("config.yaml");
Ok(!config_file.exists())
} else {
Ok(true)
}
}
StorageMode::ProjectOnly => {
if let Some(path) = global_path {
let config_file = path.join("config.yaml");
Ok(!config_file.exists())
} else {
Ok(true)
}
}
StorageMode::Merged => {
Ok(true)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_global_only_mode_loads_global() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let global_path = temp_dir.path();
let config_file = global_path.join("config.yaml");
let config_content = r#"
providers:
default_provider: openai
defaults:
model: gpt-4
steering: []
"#;
fs::write(&config_file, config_content).expect("Failed to write config");
let config =
StorageModeHandler::load_for_mode(StorageMode::GlobalOnly, Some(global_path), None)
.expect("Failed to load config");
assert_eq!(
config.providers.default_provider,
Some("openai".to_string())
);
assert_eq!(config.defaults.model, Some("gpt-4".to_string()));
}
#[test]
fn test_project_only_mode_loads_project() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let project_path = temp_dir.path();
let config_file = project_path.join("config.yaml");
let config_content = r#"
providers:
default_provider: anthropic
defaults:
model: claude-3
steering: []
"#;
fs::write(&config_file, config_content).expect("Failed to write config");
let config =
StorageModeHandler::load_for_mode(StorageMode::ProjectOnly, None, Some(project_path))
.expect("Failed to load config");
assert_eq!(
config.providers.default_provider,
Some("anthropic".to_string())
);
assert_eq!(config.defaults.model, Some("claude-3".to_string()));
}
#[test]
fn test_merged_mode_project_overrides_global() {
let global_dir = TempDir::new().expect("Failed to create temp dir");
let project_dir = TempDir::new().expect("Failed to create temp dir");
let global_config_file = global_dir.path().join("config.yaml");
let global_content = r#"
providers:
default_provider: openai
defaults:
model: gpt-4
steering: []
"#;
fs::write(&global_config_file, global_content).expect("Failed to write global config");
let project_config_file = project_dir.path().join("config.yaml");
let project_content = r#"
providers:
default_provider: anthropic
defaults:
model: claude-3
steering: []
"#;
fs::write(&project_config_file, project_content).expect("Failed to write project config");
let config = StorageModeHandler::load_for_mode(
StorageMode::Merged,
Some(global_dir.path()),
Some(project_dir.path()),
)
.expect("Failed to load config");
assert_eq!(
config.providers.default_provider,
Some("anthropic".to_string())
);
assert_eq!(config.defaults.model, Some("claude-3".to_string()));
}
#[test]
fn test_global_only_isolation() {
let global_dir = TempDir::new().expect("Failed to create temp dir");
let project_dir = TempDir::new().expect("Failed to create temp dir");
let global_config_file = global_dir.path().join("config.yaml");
fs::write(
&global_config_file,
"providers:\n default_provider: openai\ndefaults: {}\nsteering: []",
)
.expect("Failed to write global config");
let project_config_file = project_dir.path().join("config.yaml");
fs::write(
&project_config_file,
"providers:\n default_provider: anthropic\ndefaults: {}\nsteering: []",
)
.expect("Failed to write project config");
let config = StorageModeHandler::load_for_mode(
StorageMode::GlobalOnly,
Some(global_dir.path()),
Some(project_dir.path()),
)
.expect("Failed to load config");
assert_eq!(
config.providers.default_provider,
Some("openai".to_string())
);
}
#[test]
fn test_project_only_isolation() {
let global_dir = TempDir::new().expect("Failed to create temp dir");
let project_dir = TempDir::new().expect("Failed to create temp dir");
let global_config_file = global_dir.path().join("config.yaml");
fs::write(
&global_config_file,
"providers:\n default_provider: openai\ndefaults: {}\nsteering: []",
)
.expect("Failed to write global config");
let project_config_file = project_dir.path().join("config.yaml");
fs::write(
&project_config_file,
"providers:\n default_provider: anthropic\ndefaults: {}\nsteering: []",
)
.expect("Failed to write project config");
let config = StorageModeHandler::load_for_mode(
StorageMode::ProjectOnly,
Some(global_dir.path()),
Some(project_dir.path()),
)
.expect("Failed to load config");
assert_eq!(
config.providers.default_provider,
Some("anthropic".to_string())
);
}
}