use std::collections::HashMap;
use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use crate::error::MpsError;
fn default_git_remote() -> String { "origin".into() }
fn default_git_branch() -> String { "master".into() }
fn default_command() -> String { "open".into() }
fn default_type_aliases() -> HashMap<String, String> { HashMap::new() }
fn default_command_aliases() -> HashMap<String, String> { HashMap::new() }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub mps_dir: PathBuf,
pub storage_dir: PathBuf,
pub log_file: PathBuf,
#[serde(default = "default_git_remote")]
pub git_remote: String,
#[serde(default = "default_git_branch")]
pub git_branch: String,
#[serde(default = "default_command")]
pub default_command: String,
#[serde(default = "default_type_aliases", alias = "aliases")]
pub type_aliases: HashMap<String, String>,
#[serde(default = "default_command_aliases")]
pub command_aliases: HashMap<String, String>,
}
impl Config {
pub fn default_config() -> Result<Self, MpsError> {
let home = dirs::home_dir()
.ok_or_else(|| MpsError::ConfigInvalid("cannot determine home directory".into()))?;
let mps_dir = home.join(".mps");
Ok(Config {
storage_dir: mps_dir.join("mps"),
log_file: mps_dir.join("mps.log"),
mps_dir,
git_remote: "origin".into(),
git_branch: "master".into(),
default_command: "open".into(),
type_aliases: HashMap::new(),
command_aliases: HashMap::new(),
})
}
pub fn load(path: &Path) -> Result<Self, MpsError> {
if !path.exists() {
return Err(MpsError::ConfigNotFound(path.to_path_buf()));
}
let content = std::fs::read_to_string(path)?;
let normalised = content
.lines()
.map(|line| {
if let Some(rest) = line.strip_prefix(':') {
rest.to_string()
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n");
let cfg: Config = serde_yaml::from_str(&normalised)
.map_err(|e| MpsError::ConfigInvalid(e.to_string()))?;
Ok(cfg)
}
pub fn init(path: &Path) -> Result<(), MpsError> {
if path.exists() {
return Ok(());
}
let cfg = Self::default_config()?;
let yaml = serde_yaml::to_string(&cfg)?;
std::fs::write(path, yaml)?;
Ok(())
}
pub fn ensure_dirs(&self) -> Result<(), MpsError> {
std::fs::create_dir_all(&self.mps_dir)?;
std::fs::create_dir_all(&self.storage_dir)?;
if !self.log_file.exists() {
std::fs::write(&self.log_file, "")?;
}
Ok(())
}
}
pub fn default_config_path() -> PathBuf {
std::env::var("MPS_CONFIG")
.map(PathBuf::from)
.unwrap_or_else(|_| {
dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join(".mps_config.yaml")
})
}