1use std::fs;
4use std::path::{Path, PathBuf};
5
6use serde_yaml::Value;
7
8use crate::ConfigError;
9use crate::types::{AppConfig, ToolVersions};
10
11pub fn read_app_config(home: &Path) -> Result<AppConfig, ConfigError> {
13 let path = home.join("config.yaml");
14 if !path.exists() {
15 return Ok(AppConfig::default());
16 }
17
18 let content = fs::read_to_string(&path)?;
19 serde_yaml::from_str(&content).map_err(|error| ConfigError::Yaml {
20 path,
21 message: error.to_string(),
22 })
23}
24
25pub fn write_app_config(home: &Path, config: &AppConfig) -> Result<(), ConfigError> {
27 fs::create_dir_all(home)?;
28 let path = home.join("config.yaml");
29 let rendered = serde_yaml::to_string(config).map_err(|error| ConfigError::Yaml {
30 path: path.clone(),
31 message: error.to_string(),
32 })?;
33 fs::write(path, rendered)?;
34 Ok(())
35}
36
37pub fn read_tool_versions(path: &Path) -> Result<ToolVersions, ConfigError> {
39 let content = fs::read_to_string(path)?;
40 toml::from_str(&content).map_err(|error| ConfigError::Toml {
41 path: path.to_path_buf(),
42 message: error.to_string(),
43 })
44}
45
46pub fn write_tool_versions(path: &Path, tools: &ToolVersions) -> Result<(), ConfigError> {
48 if let Some(parent) = path.parent() {
49 fs::create_dir_all(parent)?;
50 }
51 let rendered = toml::to_string_pretty(tools).map_err(|error| ConfigError::Toml {
52 path: path.to_path_buf(),
53 message: error.to_string(),
54 })?;
55 fs::write(path, rendered)?;
56 Ok(())
57}
58
59pub fn flatten_app_config(config: &AppConfig) -> Vec<(String, String)> {
61 vec![
62 (
63 String::from("proxy.enable"),
64 config.proxy.enable.to_string(),
65 ),
66 (
67 String::from("proxy.url"),
68 if config.proxy.url.is_empty() {
69 String::from("<unset>")
70 } else {
71 config.proxy.url.clone()
72 },
73 ),
74 (
75 String::from("storage.sdkPath"),
76 if config.storage.sdk_path.is_empty() {
77 String::from("<unset>")
78 } else {
79 config.storage.sdk_path.clone()
80 },
81 ),
82 (
83 String::from("registry.address"),
84 if config.registry.address.is_empty() {
85 String::from("<unset>")
86 } else {
87 config.registry.address.clone()
88 },
89 ),
90 (
91 String::from("legacyVersionFile.enable"),
92 config.legacy_version_file.enable.to_string(),
93 ),
94 (
95 String::from("legacyVersionFile.strategy"),
96 config.legacy_version_file.strategy.clone(),
97 ),
98 (
99 String::from("cache.availableHookDuration"),
100 config.cache.available_hook_duration.clone(),
101 ),
102 ]
103}
104
105pub fn set_app_config_value(
107 config: &mut AppConfig,
108 key: &str,
109 value: &str,
110) -> Result<(), ConfigError> {
111 match key {
112 "proxy.enable" => {
113 config.proxy.enable = value
114 .parse::<bool>()
115 .map_err(|_| ConfigError::InvalidValue {
116 key: key.to_string(),
117 value: value.to_string(),
118 })?;
119 }
120 "proxy.url" => {
121 config.proxy.url = value.to_string();
122 }
123 "storage.sdkPath" => {
124 config.storage.sdk_path = value.to_string();
125 }
126 "registry.address" => {
127 config.registry.address = value.to_string();
128 }
129 "legacyVersionFile.enable" => {
130 config.legacy_version_file.enable =
131 value
132 .parse::<bool>()
133 .map_err(|_| ConfigError::InvalidValue {
134 key: key.to_string(),
135 value: value.to_string(),
136 })?;
137 }
138 "legacyVersionFile.strategy" => {
139 config.legacy_version_file.strategy = value.to_string();
140 }
141 "cache.availableHookDuration" => {
142 config.cache.available_hook_duration = value.to_string();
143 }
144 _ => {
145 return Err(ConfigError::UnknownKey(key.to_string()));
146 }
147 }
148 Ok(())
149}
150
151pub fn unset_app_config_value(config: &mut AppConfig, key: &str) -> Result<(), ConfigError> {
153 match key {
154 "proxy.enable" => {
155 config.proxy.enable = AppConfig::default().proxy.enable;
156 }
157 "proxy.url" => {
158 config.proxy.url.clear();
159 }
160 "storage.sdkPath" => {
161 config.storage.sdk_path.clear();
162 }
163 "registry.address" => {
164 config.registry.address.clear();
165 }
166 "legacyVersionFile.enable" => {
167 config.legacy_version_file.enable = AppConfig::default().legacy_version_file.enable;
168 }
169 "legacyVersionFile.strategy" => {
170 config.legacy_version_file.strategy = AppConfig::default().legacy_version_file.strategy;
171 }
172 "cache.availableHookDuration" => {
173 config.cache.available_hook_duration =
174 AppConfig::default().cache.available_hook_duration;
175 }
176 _ => {
177 return Err(ConfigError::UnknownKey(key.to_string()));
178 }
179 }
180 Ok(())
181}
182
183pub fn app_config_to_value(config: &AppConfig) -> Result<Value, ConfigError> {
185 serde_yaml::to_value(config).map_err(|error| ConfigError::Yaml {
186 path: PathBuf::from("config.yaml"),
187 message: error.to_string(),
188 })
189}