use std::path::{Path, PathBuf};
use super::paths;
use super::settings::BambooSettings;
#[derive(Debug, Clone)]
pub struct ResolvedSettings {
pub settings: BambooSettings,
pub source_paths: Vec<PathBuf>,
}
pub fn load_settings(project_dir: Option<&Path>) -> ResolvedSettings {
load_settings_from_dirs(&paths::user_settings_path(), project_dir)
}
fn load_settings_from_dirs(
user_settings_path: &Path,
project_dir: Option<&Path>,
) -> ResolvedSettings {
let user = BambooSettings::load_from(user_settings_path);
let mut source_paths = Vec::new();
if user_settings_path.exists() {
source_paths.push(user_settings_path.to_path_buf());
}
let mut settings = user;
if let Some(proj_dir) = project_dir {
let project_bamboo = proj_dir.join(".bamboo");
let project_path = project_bamboo.join("settings.json");
let project_settings = BambooSettings::load_from(&project_path);
if project_path.exists() {
source_paths.push(project_path);
}
let mut merged = project_settings;
merged.merge(&settings);
settings = merged;
let local_path = project_bamboo.join("settings.local.json");
let local = BambooSettings::load_from(&local_path);
if local_path.exists() {
source_paths.push(local_path);
let mut merged = local;
merged.merge(&settings);
settings = merged;
}
}
let managed_path = paths::managed_settings_path();
let managed = BambooSettings::load_from(&managed_path);
if managed_path.exists() {
source_paths.push(managed_path);
let mut merged = managed;
merged.merge(&settings);
settings = merged;
}
ResolvedSettings {
settings,
source_paths,
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
fn write_settings(dir: &Path, filename: &str, content: &str) {
let path = dir.join(filename);
std::fs::write(&path, content).unwrap();
}
#[test]
fn test_load_settings_no_files() {
let temp = TempDir::new().unwrap();
let user_path = temp.path().join("settings.json"); let resolved = load_settings_from_dirs(&user_path, None);
assert!(resolved.settings.permission_mode.is_none());
assert!(resolved.source_paths.is_empty());
}
#[test]
fn test_load_settings_user_only() {
let temp = TempDir::new().unwrap();
let user_path = temp.path().join("settings.json");
write_settings(
temp.path(),
"settings.json",
r#"{"permissionMode": "plan"}"#,
);
let resolved = load_settings_from_dirs(&user_path, None);
assert_eq!(
resolved.settings.permission_mode,
Some(crate::config::settings::PermissionMode::Plan)
);
assert_eq!(resolved.source_paths.len(), 1);
}
#[test]
fn test_load_settings_project_overrides_user() {
let temp = TempDir::new().unwrap();
let user_dir = temp.path().join("user_bamboo");
std::fs::create_dir_all(&user_dir).unwrap();
write_settings(
&user_dir,
"settings.json",
r#"{"permissionMode": "bypassPermissions", "defaultModel": "gpt-4"}"#,
);
let project_dir = temp.path().join("my_project");
let project_bamboo = project_dir.join(".bamboo");
std::fs::create_dir_all(&project_bamboo).unwrap();
write_settings(
&project_bamboo,
"settings.json",
r#"{"permissionMode": "plan"}"#,
);
let resolved = load_settings_from_dirs(&user_dir.join("settings.json"), Some(&project_dir));
assert_eq!(
resolved.settings.permission_mode,
Some(crate::config::settings::PermissionMode::Plan)
);
assert_eq!(resolved.settings.default_model, Some("gpt-4".to_string()));
}
#[test]
fn test_load_settings_local_overrides_project() {
let temp = TempDir::new().unwrap();
let user_dir = temp.path().join("user_bamboo");
std::fs::create_dir_all(&user_dir).unwrap();
write_settings(&user_dir, "settings.json", r#"{}"#);
let project_dir = temp.path().join("my_project");
let project_bamboo = project_dir.join(".bamboo");
std::fs::create_dir_all(&project_bamboo).unwrap();
write_settings(
&project_bamboo,
"settings.json",
r#"{"permissionMode": "plan"}"#,
);
write_settings(
&project_bamboo,
"settings.local.json",
r#"{"permissionMode": "acceptEdits"}"#,
);
let resolved = load_settings_from_dirs(&user_dir.join("settings.json"), Some(&project_dir));
assert_eq!(
resolved.settings.permission_mode,
Some(crate::config::settings::PermissionMode::AcceptEdits)
);
}
#[test]
fn test_managed_settings_override_all() {
let temp = TempDir::new().unwrap();
let user_dir = temp.path().join("user_bamboo");
std::fs::create_dir_all(&user_dir).unwrap();
write_settings(
&user_dir,
"settings.json",
r#"{"permissionMode": "acceptEdits", "defaultModel": "user-model"}"#,
);
let project_dir = temp.path().join("my_project");
let project_bamboo = project_dir.join(".bamboo");
std::fs::create_dir_all(&project_bamboo).unwrap();
write_settings(
&project_bamboo,
"settings.json",
r#"{"defaultModel": "project-model"}"#,
);
let managed_dir = temp.path().join("managed");
std::fs::create_dir_all(&managed_dir).unwrap();
write_settings(
&managed_dir,
"settings.json",
r#"{"permissionMode": "plan"}"#,
);
let mut resolved =
load_settings_from_dirs(&user_dir.join("settings.json"), Some(&project_dir));
let managed_path = managed_dir.join("settings.json");
let managed = BambooSettings::load_from(&managed_path);
let mut merged = managed;
merged.merge(&resolved.settings);
resolved.settings = merged;
assert_eq!(
resolved.settings.permission_mode,
Some(crate::config::settings::PermissionMode::Plan)
);
assert_eq!(
resolved.settings.default_model,
Some("project-model".to_string())
);
}
}