commit_wizard/engine/config/
resolver.rs1use crate::engine::{
2 LoggerTrait,
3 config::{BaseConfig, ProjectConfig, RulesConfig, StandardConfig},
4 constants::{resolve_global_config_path, resolve_global_rules_path},
5 error::{ErrorCode, Result},
6};
7
8pub fn resolve_global_configs() -> (Option<BaseConfig>, Option<RulesConfig>) {
9 let global_config = if let Ok(path) = resolve_global_config_path() {
11 resolve_standard_configs(&path)
12 } else {
13 None
14 };
15
16 let global_rules = if let Ok(path) = resolve_global_rules_path() {
18 load_rules_config(&path)
19 } else {
20 None
21 };
22 (global_config, global_rules)
23}
24
25pub fn resolve_project_configs(
26 path: &std::path::Path,
27 logger: Option<&dyn LoggerTrait>,
28) -> (Option<BaseConfig>, Option<RulesConfig>) {
29 if let Some(project_config) = load_project_config(path, logger) {
30 let (base_config, rules_config) = extract_configs_from_project_config(&project_config);
31 (Some(base_config), rules_config)
32 } else {
33 (None, None)
34 }
35}
36
37pub fn resolve_standard_configs(path: &std::path::Path) -> Option<BaseConfig> {
38 if let Some(standard_config) = load_standard_config(path) {
39 let base_config = extract_config_from_standard_config(&standard_config);
40 Some(base_config)
41 } else {
42 None
43 }
44}
45
46pub fn load_project_config(
47 path: &std::path::Path,
48 logger: Option<&dyn LoggerTrait>,
49) -> Option<ProjectConfig> {
50 if !path.exists() {
51 if let Some(logger) = logger {
52 let msg = format!("load_project_config: path does not exist: {:?}", path);
53 logger.debug(&msg);
54 }
55 return None;
56 }
57
58 match std::fs::read_to_string(path) {
59 Ok(content) => {
60 if let Some(logger) = logger {
61 let msg = format!(
62 "load_project_config: Read {} bytes from {:?}",
63 content.len(),
64 path
65 );
66 logger.debug(&msg);
67 }
68 match ProjectConfig::from_toml_str(&content) {
69 Ok(config) => {
70 if let Some(logger) = logger {
71 logger.debug("load_project_config: Successfully parsed config");
72 }
73 Some(config)
74 }
75 Err(e) => {
76 if let Some(logger) = logger {
77 let msg = format!("load_project_config: Parse error: {}", e);
79 logger.error(&msg);
80 for (key, value) in &e.context {
82 let ctx_msg = format!(" {}: {}", key, value);
83 logger.error(&ctx_msg);
84 }
85 }
86 None
87 }
88 }
89 }
90 Err(e) => {
91 if let Some(logger) = logger {
92 let msg = format!("load_project_config: File read error: {}", e);
93 logger.error(&msg);
94 }
95 None
96 }
97 }
98}
99
100pub fn load_standard_config(path: &std::path::Path) -> Option<StandardConfig> {
101 if !path.exists() {
102 return None;
103 }
104
105 match std::fs::read_to_string(path) {
106 Ok(content) => StandardConfig::from_toml_str(&content).ok(),
107 Err(_) => None,
108 }
109}
110
111pub fn load_rules_config(path: &std::path::Path) -> Option<RulesConfig> {
112 if !path.exists() {
113 return None;
114 }
115
116 match std::fs::read_to_string(path) {
117 Ok(content) => RulesConfig::from_toml_str(&content).ok(),
118 Err(_) => None,
119 }
120}
121
122pub fn extract_configs_from_project_config(
123 project_config: &ProjectConfig,
124) -> (BaseConfig, Option<RulesConfig>) {
125 (
126 project_config.inner.config.clone(),
127 project_config.inner.rules.clone(),
128 )
129}
130
131pub fn extract_config_from_standard_config(standard_config: &StandardConfig) -> BaseConfig {
132 standard_config.inner.clone()
133}
134
135pub fn merge_rules_into_base(base: BaseConfig, rules: &RulesConfig) -> Result<BaseConfig> {
144 let mut value = toml::Value::try_from(&base).map_err(|e| {
147 ErrorCode::SerializationFailure
148 .error()
149 .with_context("operation", "merge_rules_into_base: serialize")
150 .with_context("error", e.to_string())
151 })?;
152
153 rules.resolve_value_refs(&mut value)?;
156
157 toml::Value::try_into(value).map_err(|e| {
160 ErrorCode::SerializationFailure
161 .error()
162 .with_context("operation", "merge_rules_into_base: deserialize")
163 .with_context("error", e.to_string())
164 })
165}