commit_wizard/core/usecases/configs/
edit.rs1use std::time::Instant;
2
3use crate::{
4 core::{Context, CoreResult},
5 engine::{
6 capabilities::config::{
7 edit,
8 show::{ConfigShowFormat, ConfigShowInput, ConfigTarget, config_show as show_config},
9 },
10 constants::{PROJECT_CONFIG_FILE_NAME, app_config_dir, resolve_new_project_config_path},
11 },
12};
13
14pub fn config_unset(ctx: &Context, key: &str, global: bool) -> CoreResult<()> {
15 let ui = ctx.ui();
16 let dry_run = ctx.dry_run();
17
18 let scope = if global { "global" } else { "project" };
19 let target = if global {
20 ConfigTarget::Global
21 } else {
22 ConfigTarget::Project
23 };
24
25 let project_config_path = ctx.project_config_path();
26 let input = edit::ConfigUnsetInput {
27 cwd: ctx.cwd(),
28 target,
29 key,
30 dry_run,
31 explicit_path: project_config_path.as_deref(),
32 };
33
34 let start = Instant::now();
35 let output = edit::config_unset(&input)?;
36 let duration_ms = start.elapsed().as_millis() as u64;
37
38 let meta = ui
39 .new_output_meta()
40 .with_duration_ms(duration_ms)
41 .with_timestamp(chrono::Utc::now().to_string())
42 .with_command("config.unset".to_string())
43 .with_scope(scope.to_string())
44 .with_dry_run(dry_run);
45
46 let content = ui
47 .new_output_content()
48 .title(format!("Unset config `{}` in {} scope", output.key, scope))
49 .subtitle(format!(
50 "Path: {}, Dry run: {}",
51 output.path.display(),
52 ctx.dry_run()
53 ))
54 .data("key", output.key)
55 .data("removed", output.removed)
56 .data("path", output.path.display().to_string());
57
58 ui.print_with_meta(&content, Some(&meta), true)
59}
60
61pub fn config_set(ctx: &Context, key: &str, value: &str, global: bool) -> CoreResult<()> {
62 let ui = ctx.ui();
63 let dry_run = ctx.dry_run();
64 let scope = if global { "global" } else { "project" };
65 let target = if global {
66 ConfigTarget::Global
67 } else {
68 ConfigTarget::Project
69 };
70 let project_config_path = ctx.project_config_path();
71 let input = edit::ConfigSetInput {
72 cwd: ctx.cwd(),
73 target,
74 key,
75 value,
76 dry_run,
77 explicit_path: project_config_path.as_deref(),
78 };
79
80 let start = Instant::now();
81 let output = edit::config_set(&input)?;
82 let duration_ms = start.elapsed().as_millis() as u64;
83
84 let meta = ui
85 .new_output_meta()
86 .with_duration_ms(duration_ms)
87 .with_timestamp(chrono::Utc::now().to_string())
88 .with_command("config.set".to_string())
89 .with_scope(scope.to_string())
90 .with_dry_run(dry_run);
91
92 let content = ui
93 .new_output_content()
94 .title(format!("Set config `{}` in {} scope", output.key, scope))
95 .subtitle(format!(
96 "Path: {}, Dry run: {}",
97 output.path.display(),
98 ctx.dry_run()
99 ))
100 .data("key", output.key)
101 .data("value", output.value)
102 .data("path", output.path.display().to_string());
103
104 ui.print_with_meta(&content, Some(&meta), true)
105}
106
107pub fn config_path(ctx: &Context, global: bool) -> CoreResult<()> {
108 let ui = ctx.ui();
109 let scope = if global { "global" } else { "project" };
110
111 let path = if global {
112 app_config_dir()?.join(PROJECT_CONFIG_FILE_NAME)
113 } else {
114 let project_config_path = ctx.project_config_path();
115 ctx.project_config_path().unwrap_or_else(|| {
116 resolve_new_project_config_path(
117 ctx.cwd(),
118 Some(ctx.repo_root().as_path()),
119 ctx.in_git_repo(),
120 project_config_path.as_deref(),
121 true,
122 )
123 })
124 };
125
126 let meta = ui
127 .new_output_meta()
128 .with_timestamp(chrono::Utc::now().to_string())
129 .with_command("config.path".to_string())
130 .with_scope(scope.to_string());
131
132 let content = ui
133 .new_output_content()
134 .title(format!("Config path for {} scope", scope))
135 .data("path", path.display().to_string());
136
137 ui.print_with_meta(&content, Some(&meta), true)
138}
139
140pub fn config_show(ctx: &Context, global: bool) -> CoreResult<()> {
141 let ui = ctx.ui();
142 let scope = if global { "global" } else { "project" };
143 let target = if global {
144 ConfigTarget::Global
145 } else {
146 ConfigTarget::Project
147 };
148 let project_config_path = ctx.project_config_path();
149 let input = ConfigShowInput {
150 cwd: ctx.cwd(),
151 target,
152 explicit_path: project_config_path.as_deref(),
153 format: ConfigShowFormat::Human,
154 };
155
156 let start = Instant::now();
157 let output = show_config(&input)?;
158 let duration_ms = start.elapsed().as_millis() as u64;
159
160 let meta = ui
161 .new_output_meta()
162 .with_duration_ms(duration_ms)
163 .with_timestamp(chrono::Utc::now().to_string())
164 .with_command("config.show".to_string())
165 .with_scope(scope.to_string());
166
167 let content = ui
168 .new_output_content()
169 .title(format!("Config for {} scope", scope))
170 .subtitle(format!("Path: {}", output.path.display()))
171 .data("path", output.path.display().to_string())
172 .data("exists", output.exists)
173 .data("content", output.content);
174
175 ui.print_with_meta(&content, Some(&meta), true)
176}
177
178pub fn config_get(ctx: &Context, key: &str, global: bool) -> CoreResult<()> {
179 let ui = ctx.ui();
180 let scope = if global { "global" } else { "project" };
181 let target = if global {
182 ConfigTarget::Global
183 } else {
184 ConfigTarget::Project
185 };
186 let project_config_path = ctx.project_config_path();
187 let input = edit::ConfigGetInput {
188 cwd: ctx.cwd(),
189 target,
190 key,
191 explicit_path: project_config_path.as_deref(),
192 };
193
194 let start = Instant::now();
195 let output = edit::config_get(&input)?;
196 let duration_ms = start.elapsed().as_millis() as u64;
197
198 let meta = ui
199 .new_output_meta()
200 .with_duration_ms(duration_ms)
201 .with_timestamp(chrono::Utc::now().to_string())
202 .with_command("config.get".to_string())
203 .with_scope(scope.to_string());
204
205 let content = ui
206 .new_output_content()
207 .title(format!("Config `{}` in {} scope", output.key, scope))
208 .data("key", output.key)
209 .data("value", output.value.to_string())
210 .data("path", output.path.display().to_string());
211
212 ui.print_with_meta(&content, Some(&meta), true)
213}