Skip to main content

flow_core/
config.rs

1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Config {
6    pub projects_dir: PathBuf,
7    pub state_dir: PathBuf,
8    pub default_base_branch: String,
9}
10
11impl Default for Config {
12    fn default() -> Self {
13        Self {
14            projects_dir: home_dir().join("Projects"),
15            state_dir: state_dir().join("flow"),
16            default_base_branch: "main".to_string(),
17        }
18    }
19}
20
21fn home_dir() -> PathBuf {
22    dirs::home_dir().unwrap_or_else(std::env::temp_dir)
23}
24
25fn config_dir() -> PathBuf {
26    dirs::config_dir().unwrap_or_else(|| home_dir().join(".config"))
27}
28
29fn state_dir() -> PathBuf {
30    dirs::state_dir()
31        .or_else(dirs::data_local_dir)
32        .unwrap_or_else(|| home_dir().join(".local").join("state"))
33}
34
35impl Config {
36    /// Load configuration from `~/.config/flow/config.toml` or return defaults.
37    ///
38    /// # Errors
39    ///
40    /// Returns an error if the config file exists but cannot be read or parsed.
41    pub fn load() -> Result<Self, crate::FlowError> {
42        let config_path = config_dir().join("flow").join("config.toml");
43
44        if config_path.exists() {
45            let content = std::fs::read_to_string(&config_path)?;
46            Ok(toml::from_str(&content)?)
47        } else {
48            Ok(Self::default())
49        }
50    }
51}