1use anyhow::Result;
2use colored::*;
3use std::fs;
4use std::path::PathBuf;
5use toml::{map::Map, Value};
6use clap::Subcommand;
7#[derive(Subcommand, Debug)]
8pub enum OptimizeAction {
9 Aggressive,
10 Balanced,
11 Conservative,
12 Custom {
13 #[arg(default_value = "4")]
14 jobs: u32,
15 #[arg(default_value = "true")]
16 incremental: String,
17 #[arg(default_value = "1")]
18 opt_level: u32,
19 #[arg(default_value = "1")]
20 debug_level: u32,
21 #[arg(default_value = "128")]
22 codegen_units: u32,
23 },
24 Status,
25 Recommendations,
26 Restore,
27}
28pub struct BuildOptimizer {
29 project_root: PathBuf,
30}
31impl BuildOptimizer {
32 pub fn new(project_root: Option<PathBuf>) -> Result<Self> {
33 let project_root = project_root
34 .unwrap_or_else(|| {
35 std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
36 });
37 Ok(Self { project_root })
38 }
39 pub fn optimize_build(&self, profile: OptimizationProfile) -> Result<()> {
40 let cargo_toml_path = self.project_root.join("Cargo.toml");
41 if !cargo_toml_path.exists() {
42 return Err(
43 anyhow::anyhow!(
44 "Cargo.toml not found in {}", self.project_root.display()
45 ),
46 );
47 }
48 let content = fs::read_to_string(&cargo_toml_path)?;
49 let mut config: Value = toml::from_str(&content)?;
50 match profile {
51 OptimizationProfile::Aggressive => {
52 self.apply_aggressive_optimizations(&mut config)?
53 }
54 OptimizationProfile::Balanced => {
55 self.apply_balanced_optimizations(&mut config)?
56 }
57 OptimizationProfile::Conservative => {
58 self.apply_conservative_optimizations(&mut config)?
59 }
60 OptimizationProfile::Custom {
61 jobs,
62 incremental,
63 opt_level,
64 debug_level,
65 codegen_units,
66 } => {
67 self.apply_custom_optimizations(
68 &mut config,
69 jobs,
70 incremental,
71 opt_level,
72 debug_level,
73 codegen_units,
74 )?;
75 }
76 }
77 let backup_path = cargo_toml_path.with_extension("toml.backup");
78 fs::copy(&cargo_toml_path, &backup_path)?;
79 println!("š Backed up Cargo.toml to {}", backup_path.display());
80 let optimized_content = toml::to_string_pretty(&config)?;
81 fs::write(&cargo_toml_path, optimized_content)?;
82 println!("ā
Applied {} optimizations to Cargo.toml", profile.to_string());
83 self.show_optimization_summary(&config)?;
84 Ok(())
85 }
86 fn apply_aggressive_optimizations(&self, config: &mut Value) -> Result<()> {
87 if !config.as_table().unwrap().contains_key("build") {
88 config
89 .as_table_mut()
90 .unwrap()
91 .insert("build".to_string(), Value::Table(Map::new()));
92 }
93 let build = config.get_mut("build").unwrap().as_table_mut().unwrap();
94 build.insert("jobs".to_string(), Value::Integer(8));
95 build.insert("incremental".to_string(), Value::Boolean(true));
96 if !config.as_table().unwrap().contains_key("profile") {
97 config
98 .as_table_mut()
99 .unwrap()
100 .insert("profile".to_string(), Value::Table(Map::new()));
101 }
102 let profile = config.get_mut("profile").unwrap().as_table_mut().unwrap();
103 if !profile.contains_key("dev") {
104 profile.insert("dev".to_string(), Value::Table(Map::new()));
105 }
106 let dev = profile.get_mut("dev").unwrap().as_table_mut().unwrap();
107 dev.insert("opt-level".to_string(), Value::Integer(1));
108 dev.insert("debug".to_string(), Value::Integer(1));
109 dev.insert("codegen-units".to_string(), Value::Integer(256));
110 dev.insert("lto".to_string(), Value::Boolean(false));
111 if !config.as_table().unwrap().contains_key("env") {
112 config
113 .as_table_mut()
114 .unwrap()
115 .insert("env".to_string(), Value::Table(Map::new()));
116 }
117 let env = config.get_mut("env").unwrap().as_table_mut().unwrap();
118 env.insert("CARGO_INCREMENTAL".to_string(), Value::String("1".to_string()));
119 env.insert("CARGO_BUILD_JOBS".to_string(), Value::String("8".to_string()));
120 Ok(())
121 }
122 fn apply_balanced_optimizations(&self, config: &mut Value) -> Result<()> {
123 if !config.as_table().unwrap().contains_key("build") {
124 config
125 .as_table_mut()
126 .unwrap()
127 .insert("build".to_string(), Value::Table(Map::new()));
128 }
129 let build = config.get_mut("build").unwrap().as_table_mut().unwrap();
130 build.insert("jobs".to_string(), Value::Integer(4));
131 build.insert("incremental".to_string(), Value::Boolean(true));
132 if !config.as_table().unwrap().contains_key("profile") {
133 config
134 .as_table_mut()
135 .unwrap()
136 .insert("profile".to_string(), Value::Table(Map::new()));
137 }
138 let profile = config.get_mut("profile").unwrap().as_table_mut().unwrap();
139 if !profile.contains_key("dev") {
140 profile.insert("dev".to_string(), Value::Table(Map::new()));
141 }
142 let dev = profile.get_mut("dev").unwrap().as_table_mut().unwrap();
143 dev.insert("opt-level".to_string(), Value::Integer(1));
144 dev.insert("debug".to_string(), Value::Integer(1));
145 dev.insert("codegen-units".to_string(), Value::Integer(128));
146 dev.insert("lto".to_string(), Value::Boolean(false));
147 if !config.as_table().unwrap().contains_key("env") {
148 config
149 .as_table_mut()
150 .unwrap()
151 .insert("env".to_string(), Value::Table(Map::new()));
152 }
153 let env = config.get_mut("env").unwrap().as_table_mut().unwrap();
154 env.insert("CARGO_INCREMENTAL".to_string(), Value::String("1".to_string()));
155 env.insert("CARGO_BUILD_JOBS".to_string(), Value::String("4".to_string()));
156 Ok(())
157 }
158 fn apply_conservative_optimizations(&self, config: &mut Value) -> Result<()> {
159 if !config.as_table().unwrap().contains_key("build") {
160 config
161 .as_table_mut()
162 .unwrap()
163 .insert("build".to_string(), Value::Table(Map::new()));
164 }
165 let build = config.get_mut("build").unwrap().as_table_mut().unwrap();
166 build.insert("jobs".to_string(), Value::Integer(2));
167 build.insert("incremental".to_string(), Value::Boolean(true));
168 if !config.as_table().unwrap().contains_key("profile") {
169 config
170 .as_table_mut()
171 .unwrap()
172 .insert("profile".to_string(), Value::Table(Map::new()));
173 }
174 let profile = config.get_mut("profile").unwrap().as_table_mut().unwrap();
175 if !profile.contains_key("dev") {
176 profile.insert("dev".to_string(), Value::Table(Map::new()));
177 }
178 let dev = profile.get_mut("dev").unwrap().as_table_mut().unwrap();
179 dev.insert("opt-level".to_string(), Value::Integer(0));
180 dev.insert("debug".to_string(), Value::Integer(2));
181 dev.insert("codegen-units".to_string(), Value::Integer(64));
182 dev.insert("lto".to_string(), Value::Boolean(false));
183 if !config.as_table().unwrap().contains_key("env") {
184 config
185 .as_table_mut()
186 .unwrap()
187 .insert("env".to_string(), Value::Table(Map::new()));
188 }
189 let env = config.get_mut("env").unwrap().as_table_mut().unwrap();
190 env.insert("CARGO_INCREMENTAL".to_string(), Value::String("1".to_string()));
191 env.insert("CARGO_BUILD_JOBS".to_string(), Value::String("2".to_string()));
192 Ok(())
193 }
194 fn apply_custom_optimizations(
195 &self,
196 config: &mut Value,
197 jobs: u32,
198 incremental: bool,
199 opt_level: u32,
200 debug_level: u32,
201 codegen_units: u32,
202 ) -> Result<()> {
203 if !config.as_table().unwrap().contains_key("build") {
204 config
205 .as_table_mut()
206 .unwrap()
207 .insert("build".to_string(), Value::Table(Map::new()));
208 }
209 let build = config.get_mut("build").unwrap().as_table_mut().unwrap();
210 build.insert("jobs".to_string(), Value::Integer(jobs as i64));
211 build.insert("incremental".to_string(), Value::Boolean(incremental));
212 if !config.as_table().unwrap().contains_key("profile") {
213 config
214 .as_table_mut()
215 .unwrap()
216 .insert("profile".to_string(), Value::Table(Map::new()));
217 }
218 let profile = config.get_mut("profile").unwrap().as_table_mut().unwrap();
219 if !profile.contains_key("dev") {
220 profile.insert("dev".to_string(), Value::Table(Map::new()));
221 }
222 let dev = profile.get_mut("dev").unwrap().as_table_mut().unwrap();
223 dev.insert("opt-level".to_string(), Value::Integer(opt_level as i64));
224 dev.insert("debug".to_string(), Value::Integer(debug_level as i64));
225 dev.insert("codegen-units".to_string(), Value::Integer(codegen_units as i64));
226 dev.insert("lto".to_string(), Value::Boolean(false));
227 if !config.as_table().unwrap().contains_key("env") {
228 config
229 .as_table_mut()
230 .unwrap()
231 .insert("env".to_string(), Value::Table(Map::new()));
232 }
233 let env = config.get_mut("env").unwrap().as_table_mut().unwrap();
234 env.insert(
235 "CARGO_INCREMENTAL".to_string(),
236 Value::String(if incremental { "1" } else { "0" }.to_string()),
237 );
238 env.insert("CARGO_BUILD_JOBS".to_string(), Value::String(jobs.to_string()));
239 Ok(())
240 }
241 fn show_optimization_summary(&self, config: &Value) -> Result<()> {
242 println!("\nš Build Optimization Summary:");
243 println!("{}", "ā".repeat(50).blue());
244 if let Some(build) = config.get("build") {
245 if let Some(jobs) = build.get("jobs") {
246 println!("š Parallel Jobs: {}", jobs);
247 }
248 if let Some(incremental) = build.get("incremental") {
249 println!("š Incremental: {}", incremental);
250 }
251 }
252 if let Some(profile) = config.get("profile") {
253 if let Some(dev) = profile.get("dev") {
254 if let Some(opt_level) = dev.get("opt-level") {
255 println!("ā” Optimization Level: {}", opt_level);
256 }
257 if let Some(debug) = dev.get("debug") {
258 println!("š Debug Level: {}", debug);
259 }
260 if let Some(codegen_units) = dev.get("codegen-units") {
261 println!("šļø Codegen Units: {}", codegen_units);
262 }
263 if let Some(lto) = dev.get("lto") {
264 println!("š Link-Time Optimization: {}", lto);
265 }
266 }
267 }
268 if let Some(env) = config.get("env") {
269 println!("\nš Environment Variables:");
270 for (key, value) in env.as_table().unwrap() {
271 println!(" {} = {}", key, value);
272 }
273 }
274 println!("{}", "ā".repeat(50).blue());
275 println!("š” Run 'cargo build' to see the speed improvements!");
276 Ok(())
277 }
278 pub fn restore_backup(&self) -> Result<()> {
279 let cargo_toml_path = self.project_root.join("Cargo.toml");
280 let backup_path = cargo_toml_path.with_extension("toml.backup");
281 if !backup_path.exists() {
282 return Err(anyhow::anyhow!("No backup found to restore"));
283 }
284 fs::copy(&backup_path, &cargo_toml_path)?;
285 println!("ā
Restored Cargo.toml from backup");
286 Ok(())
287 }
288 pub fn show_status(&self) -> Result<()> {
289 let cargo_toml_path = self.project_root.join("Cargo.toml");
290 if !cargo_toml_path.exists() {
291 return Err(anyhow::anyhow!("Cargo.toml not found"));
292 }
293 let content = fs::read_to_string(&cargo_toml_path)?;
294 let config: Value = toml::from_str(&content)?;
295 println!("š Current Build Optimization Status:");
296 println!("{}", "ā".repeat(50).blue());
297 if let Some(build) = config.get("build") {
298 println!("š Build Configuration:");
299 for (key, value) in build.as_table().unwrap() {
300 println!(" {}: {}", key, value);
301 }
302 } else {
303 println!("š Build Configuration: Not configured");
304 }
305 if let Some(profile) = config.get("profile") {
306 if let Some(dev) = profile.get("dev") {
307 println!("\nā” Dev Profile:");
308 for (key, value) in dev.as_table().unwrap() {
309 println!(" {}: {}", key, value);
310 }
311 }
312 }
313 if let Some(env) = config.get("env") {
314 println!("\nš Environment Variables:");
315 for (key, value) in env.as_table().unwrap() {
316 println!(" {}: {}", key, value);
317 }
318 }
319 println!("{}", "ā".repeat(50).blue());
320 Ok(())
321 }
322 pub fn get_optimal_jobs(&self) -> u32 {
323 std::thread::available_parallelism().map(|n| n.get() as u32).unwrap_or(4)
324 }
325 pub fn show_recommendations(&self) -> Result<()> {
326 let cpu_count = self.get_optimal_jobs();
327 println!("š” Build Optimization Recommendations:");
328 println!("{}", "ā".repeat(50).blue());
329 println!("š„ļø CPU Cores: {}", cpu_count);
330 println!("š Recommended Jobs: {}", cpu_count);
331 println!();
332 println!("š Aggressive Profile:");
333 println!(" - Parallel jobs: {}", cpu_count);
334 println!(" - Incremental: true");
335 println!(" - Opt level: 1 (basic optimizations)");
336 println!(" - Codegen units: 256 (maximum parallelism)");
337 println!(" - Debug: 1 (reduced debug info)");
338 println!();
339 println!("āļø Balanced Profile:");
340 println!(" - Parallel jobs: {}", cpu_count / 2);
341 println!(" - Incremental: true");
342 println!(" - Opt level: 1 (basic optimizations)");
343 println!(" - Codegen units: 128 (moderate parallelism)");
344 println!(" - Debug: 1 (reduced debug info)");
345 println!();
346 println!("š”ļø Conservative Profile:");
347 println!(" - Parallel jobs: 2");
348 println!(" - Incremental: true");
349 println!(" - Opt level: 0 (no optimizations)");
350 println!(" - Codegen units: 64 (minimal parallelism)");
351 println!(" - Debug: 2 (full debug info)");
352 println!();
353 println!("š” Use 'cm optimize aggressive' for maximum speed");
354 println!("š” Use 'cm optimize balanced' for good speed/stability");
355 println!("š” Use 'cm optimize conservative' for maximum stability");
356 Ok(())
357 }
358}
359#[derive(Debug, Clone)]
360pub enum OptimizationProfile {
361 Aggressive,
362 Balanced,
363 Conservative,
364 Custom {
365 jobs: u32,
366 incremental: bool,
367 opt_level: u32,
368 debug_level: u32,
369 codegen_units: u32,
370 },
371}
372impl OptimizationProfile {
373 pub fn to_string(&self) -> &'static str {
374 match self {
375 OptimizationProfile::Aggressive => "Aggressive",
376 OptimizationProfile::Balanced => "Balanced",
377 OptimizationProfile::Conservative => "Conservative",
378 OptimizationProfile::Custom { .. } => "Custom",
379 }
380 }
381}
382pub fn check_crew_operations(command: &str) -> Result<bool> {
385 println!(
386 "š„ Crew checking operations for command '{}' - all hands accounted for!",
387 command.cyan()
388 );
389 let license_manager = crate::license::LicenseManager::new()?;
390 match license_manager.enforce_license(command) {
391 Ok(_) => {
392 println!(
393 "ā
Crew reports: Command '{}' ready for operations!", command.green()
394 );
395 println!(" š„ All crew stations manned - ready to execute!");
396 Ok(true)
397 }
398 Err(e) => {
399 if e.to_string().contains("limit") {
400 println!("ā ļø Crew warning: Operation quota exceeded!");
401 println!(" š„ Resupply crew at: https://cargo.do/checkout");
402 println!(" š„ Upgrade for unlimited crew operations");
403 } else if e.to_string().contains("License not found") {
404 println!("ā Crew emergency: No operation authorization!");
405 println!(" š„ Get clearance with 'cm register <key>'");
406 } else {
407 println!(
408 "ā Crew distress: Operations check failed: {}", e.to_string().red()
409 );
410 println!(" š„ Secure all stations - prepare for inspection!");
411 }
412 Ok(false)
413 }
414 }
415}