Skip to main content

cargo_mate/captain/
optimize.rs

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}
382/// šŸ¦€ **Crew Function #8**
383/// Ship crew that validates command operations
384pub 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}