1use crate::migration::MigrationConfig;
2use anyhow::Result;
3use serde::{Deserialize, Serialize};
4use std::fs;
5use std::path::Path;
6
7#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
31pub struct Config {
32 pub migration: MigrationConfig,
34}
35
36impl Config {
37 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn load() -> Result<Self> {
44 Self::load_from(Path::new("Toasty.toml"))
45 }
46
47 pub fn load_from(path: &Path) -> Result<Self> {
49 let contents = fs::read_to_string(path)?;
50 let config: Config = toml::from_str(&contents)?;
51 Ok(config)
52 }
53
54 pub fn load_or_default(project_root: &Path) -> Result<Self> {
57 let path = project_root.join("Toasty.toml");
58 if path.exists() {
59 Self::load_from(&path)
60 } else {
61 let config = Self::default();
62 let toml = toml::to_string_pretty(&config)?;
63 fs::write(&path, toml)?;
64 Ok(config)
65 }
66 }
67
68 pub fn migration(mut self, migration: MigrationConfig) -> Self {
70 self.migration = migration;
71 self
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use tempfile::tempdir;
79
80 #[test]
81 fn load_or_default_creates_toasty_toml_when_missing() {
82 let dir = tempdir().unwrap();
83 let path = dir.path().join("Toasty.toml");
84 assert!(!path.exists());
85
86 Config::load_or_default(dir.path()).unwrap();
87
88 assert!(path.exists(), "Toasty.toml should be created on first load");
89 let contents = fs::read_to_string(&path).unwrap();
90 let reparsed: Config = toml::from_str(&contents).unwrap();
91 let default = Config::default();
92
93 assert_eq!(reparsed, default);
94 }
95}