commit_wizard/engine/models/runtime/
resolution.rs1use crate::engine::{
2 config::{BaseConfig, RulesConfig},
3 constants::app_config_dir,
4 models::policy::Policy,
5};
6use std::{collections::BTreeMap, path::PathBuf};
7
8#[derive(Debug, Clone)]
9pub struct RuntimeResolution {
10 pub sources: AvailableConfigOptions,
12 pub config: Option<ResolvedConfig>,
14 pub policy: Policy,
16}
17
18impl Default for RuntimeResolution {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl RuntimeResolution {
25 pub fn new() -> Self {
26 Self {
27 sources: AvailableConfigOptions::new(),
28 config: None,
29 policy: Policy::default(),
30 }
31 }
32}
33
34#[derive(Debug, Clone)]
35pub struct ResolvedConfig {
36 pub path: Option<PathBuf>,
38 pub rules: RulesConfig,
41 pub base: BaseConfig,
45}
46
47#[derive(Debug, Clone)]
48pub struct RuntimePaths {
49 pub cwd: PathBuf,
51 pub global: RuntimeGlobalPaths,
53 pub in_git_repo: bool,
55 pub repo_root: Option<PathBuf>,
57 pub explicit_config_path: Option<PathBuf>,
59 pub explicit_registry: Option<String>,
61 pub explicit_registry_ref: Option<String>,
63 pub explicit_registry_section: Option<String>,
65}
66
67impl Default for RuntimePaths {
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl RuntimePaths {
74 pub fn new() -> Self {
75 let cwd = std::env::current_dir().unwrap_or_else(|e| {
76 eprintln!("[warn] Failed to determine current directory: {e} — using '.'");
77 PathBuf::from(".")
78 });
79 let global = RuntimeGlobalPaths::new().unwrap_or_else(|e| {
80 eprintln!(
81 "[warn] Failed to resolve global paths: {e} — using '.' for config/cache/state"
82 );
83 RuntimeGlobalPaths {
84 config: PathBuf::from("."),
85 cache: PathBuf::from("."),
86 state: PathBuf::from("."),
87 }
88 });
89 Self {
90 cwd,
91 global,
92 in_git_repo: false,
93 repo_root: None,
94 explicit_config_path: None,
95 explicit_registry: None,
96 explicit_registry_ref: None,
97 explicit_registry_section: None,
98 }
99 }
100}
101
102#[derive(Debug, Clone)]
103pub struct RuntimeGlobalPaths {
104 pub config: PathBuf,
106 pub cache: PathBuf,
108 pub state: PathBuf,
110}
111
112impl RuntimeGlobalPaths {
113 pub fn new() -> crate::engine::error::Result<Self> {
114 use crate::engine::constants::{app_cache_dir, app_state_dir};
115 let config = app_config_dir()?;
116 let cache = app_cache_dir()?;
117 let state = app_state_dir()?;
118 Ok(Self {
119 config,
120 cache,
121 state,
122 })
123 }
124}
125
126impl Default for RuntimeGlobalPaths {
127 fn default() -> Self {
128 Self::new().unwrap_or_else(|e| {
129 eprintln!(
130 "[warn] Failed to resolve global paths: {e} — using '.' for config/cache/state"
131 );
132 Self {
133 config: std::path::PathBuf::from("."),
134 cache: std::path::PathBuf::from("."),
135 state: std::path::PathBuf::from("."),
136 }
137 })
138 }
139}
140
141#[derive(Debug, Clone)]
142pub struct AvailableConfigOptions {
143 pub cli_config: Option<AvailableConfig>,
144 pub env_config: Option<AvailableConfig>,
146 pub repo_config: Option<AvailableConfig>,
147 pub global_config: Option<AvailableConfig>,
148 pub registries: Vec<RegistryOptions>,
150}
151
152impl Default for AvailableConfigOptions {
153 fn default() -> Self {
154 Self::new()
155 }
156}
157
158impl AvailableConfigOptions {
159 pub fn new() -> Self {
160 Self {
161 cli_config: None,
162 env_config: None,
163 repo_config: None,
164 global_config: None,
165 registries: vec![],
166 }
167 }
168
169 pub fn is_empty(&self) -> bool {
170 self.cli_config.is_none()
171 && self.env_config.is_none()
172 && self.repo_config.is_none()
173 && self.global_config.is_none()
174 && self.registries.is_empty()
175 }
176
177 pub fn has_cli_config(&self) -> bool {
178 self.cli_config.is_some()
179 }
180
181 pub fn set_cli_config(&mut self, config: AvailableConfig) -> &mut Self {
182 self.cli_config = Some(config);
183 self
184 }
185
186 pub fn has_repo_config(&self) -> bool {
187 self.repo_config.is_some()
188 }
189
190 pub fn set_repo_config(&mut self, config: AvailableConfig) -> &mut Self {
191 self.repo_config = Some(config);
192 self
193 }
194
195 pub fn has_global_config(&self) -> bool {
196 self.global_config.is_some()
197 }
198
199 pub fn set_global_config(&mut self, config: AvailableConfig) -> &mut Self {
200 self.global_config = Some(config);
201 self
202 }
203
204 pub fn has_registries(&self) -> bool {
205 !self.registries.is_empty()
206 }
207
208 pub fn registry_count(&self) -> usize {
209 self.registries.len()
210 }
211}
212
213#[derive(Debug, Clone)]
214pub struct RegistryOptions {
215 pub id: String,
217 pub tag: String,
220 pub url: String,
222 pub r#ref: String,
224 pub section: Option<String>,
226 pub config: Option<AvailableConfig>,
228 pub sections: Option<BTreeMap<String, AvailableConfig>>,
230 pub is_active: bool,
232}
233
234#[derive(Debug, Clone)]
235pub struct AvailableConfig {
236 pub rules: Option<RulesConfig>,
237 pub base: Option<BaseConfig>,
238}
239
240pub fn resolve_available_config(
241 base: Option<BaseConfig>,
242 rules: Option<RulesConfig>,
243) -> AvailableConfig {
244 AvailableConfig { base, rules }
245}
246
247pub fn resolve_policy(config: Option<&ResolvedConfig>) -> Policy {
248 match config {
249 Some(cfg) => Policy::from_config(cfg),
250 None => Policy::default(),
251 }
252}