hyprshell_core_lib/config/
load.rs

1use crate::config;
2use crate::config::{Config, check};
3use anyhow::{Context, bail};
4use ron::Options;
5use ron::extensions::Extensions;
6use std::ffi::OsStr;
7use std::path::Path;
8use tracing::{Level, debug, info, span, warn};
9
10pub fn load_config(config_path: &Path) -> anyhow::Result<Config> {
11    let _span = span!(Level::TRACE, "load_config", path =? config_path).entered();
12    if !config_path.exists() {
13        bail!("Config file does not exist, create it using `hyprshell config generate`");
14    }
15    let config = match config_path.extension().and_then(OsStr::to_str) {
16        None | Some("ron") => {
17            let options = Options::default()
18                .with_default_extension(Extensions::IMPLICIT_SOME)
19                .with_default_extension(Extensions::UNWRAP_NEWTYPES)
20                .with_default_extension(Extensions::UNWRAP_VARIANT_NEWTYPES);
21            let file = std::fs::File::open(config_path)
22                .with_context(|| format!("Failed to open config at ({config_path:?})"))?;
23            options
24                .from_reader(file)
25                .context("Failed to read ron config")
26        }
27        Some("json") => {
28            let file = std::fs::File::open(config_path)
29                .with_context(|| format!("Failed to open config at ({config_path:?})"))?;
30            serde_json::from_reader(file).context("Failed to read json config")
31        }
32        #[cfg(feature = "toml_config")]
33        Some("toml") => {
34            use std::io::Read;
35            let mut file = std::fs::File::open(config_path)
36                .with_context(|| format!("Failed to open config at ({config_path:?})"))?;
37            let mut content = String::new();
38            file.read_to_string(&mut content)
39                .context("Failed to read toml config")?;
40            toml::from_str(&content).context("Failed to parse toml config")
41        }
42        Some(ext) => bail!(
43            "Invalid config file extension: {} (check `FEATURES: ` debug log to see enabled extensions)",
44            ext
45        ),
46    };
47
48    let config = match config {
49        Ok(cfg) => cfg,
50        Err(err) => {
51            warn!("Failed to load config: {err:?}");
52            info!("Attempting to migrate config");
53            let migrated = config::migrate::migrate(config_path);
54            match migrated {
55                Ok(cfg) => {
56                    info!("Config migrated successfully");
57                    cfg
58                }
59                Err(err) => {
60                    warn!("Migration failed: {err:?}");
61                    bail!("Failed to load config and migration failed");
62                }
63            }
64        }
65    };
66    debug!("Loaded config");
67
68    check(&config)?;
69
70    Ok(config)
71}