1use serde::{Deserialize, Serialize};
3use std::fs;
4use std::path::{Path, PathBuf};
5
6use super::error::{Error, Result};
7
8#[derive(Debug, Serialize, Deserialize)]
10pub struct Config {
11 pub templates_dir: PathBuf,
13 pub preferences: Preferences,
15}
16
17#[derive(Debug, Serialize, Deserialize)]
19pub struct Preferences {
20 #[serde(default = "default_git")]
22 pub git: bool,
23 #[serde(default = "default_build")]
25 pub build: bool,
26 #[serde(default = "default_interactive")]
28 pub interactive: bool,
29}
30
31fn default_git() -> bool {
32 true
33}
34
35fn default_build() -> bool {
36 false
37}
38
39fn default_interactive() -> bool {
40 true
41}
42
43impl Default for Config {
44 fn default() -> Self {
45 let mut templates_dir = dirs::home_dir()
46 .expect("Failed to get home directory")
47 .join(".ferrisup")
48 .join("templates");
49
50 if Path::new("templates").exists() {
52 templates_dir = PathBuf::from("templates");
53 }
54
55 Self {
56 templates_dir,
57 preferences: Preferences::default(),
58 }
59 }
60}
61
62impl Default for Preferences {
63 fn default() -> Self {
64 Self {
65 git: default_git(),
66 build: default_build(),
67 interactive: default_interactive(),
68 }
69 }
70}
71
72impl Config {
73 pub fn load(path: &Path) -> Result<Self> {
75 let content = fs::read_to_string(path).map_err(|e| Error::Config(format!("Failed to read config file: {}", e)))?;
76 let config: Config = serde_json::from_str(&content).map_err(|e| Error::Config(format!("Invalid config format: {}", e)))?;
77 Ok(config)
78 }
79
80 pub fn save(&self, path: &Path) -> Result<()> {
82 let content = serde_json::to_string_pretty(self).map_err(|e| Error::Config(format!("Failed to serialize config: {}", e)))?;
83 fs::write(path, content).map_err(|e| Error::Config(format!("Failed to write config file: {}", e)))?;
84 Ok(())
85 }
86
87 pub fn default_path() -> PathBuf {
89 dirs::config_dir()
90 .expect("Failed to get config directory")
91 .join("ferrisup")
92 .join("config.json")
93 }
94
95 pub fn get_config_path() -> PathBuf {
97 let local_config = Path::new("ferrisup.json");
99 if local_config.exists() {
100 return local_config.to_path_buf();
101 }
102
103 Self::default_path()
105 }
106
107 pub fn get_default_config() -> Self {
109 Self::default()
110 }
111}