ferrous_forge/commands/
init.rs

1//! Initialize command implementation
2
3use crate::{Result, config::Config};
4use console::style;
5
6/// Execute the init command
7pub async fn execute(force: bool) -> Result<()> {
8    println!("{}", style("🔨 Initializing Ferrous Forge...").bold().cyan());
9
10    // Check if already initialized
11    let config = Config::load_or_default().await?;
12    if config.is_initialized() && !force {
13        println!("{}", style("✅ Ferrous Forge is already initialized!").green());
14        println!("Use --force to reinitialize.");
15        return Ok(());
16    }
17
18    // Create configuration directories
19    println!("📁 Creating configuration directories...");
20    config.ensure_directories().await?;
21
22    // Install system-wide cargo hijacking
23    println!("🔧 Setting up cargo command hijacking...");
24    install_cargo_hijacking().await?;
25
26    // Copy clippy configuration
27    println!("📋 Installing clippy configuration...");
28    install_clippy_config().await?;
29
30    // Setup shell integration
31    println!("🐚 Installing shell integration...");
32    install_shell_integration().await?;
33
34    // Mark as initialized
35    let mut config = config;
36    config.mark_initialized();
37    config.save().await?;
38
39    println!("{}", style("🎉 Ferrous Forge initialization complete!").bold().green());
40    println!();
41    println!("Next steps:");
42    println!("• Restart your shell or run: source ~/.bashrc");
43    println!("• Create a new project: cargo new my-project");
44    println!("• All new projects will automatically use Edition 2024 + strict standards!");
45
46    Ok(())
47}
48
49async fn install_cargo_hijacking() -> Result<()> {
50    // This will create wrapper scripts that intercept cargo commands
51    // and apply our standards before delegating to the real cargo
52    
53    let home_dir = dirs::home_dir()
54        .ok_or_else(|| crate::Error::config("Could not find home directory"))?;
55    
56    let bin_dir = home_dir.join(".local").join("bin");
57    tokio::fs::create_dir_all(&bin_dir).await?;
58
59    // Create cargo wrapper script
60    let cargo_wrapper = include_str!("../../templates/cargo-wrapper.sh");
61    let cargo_path = bin_dir.join("cargo");
62    tokio::fs::write(&cargo_path, cargo_wrapper).await?;
63
64    // Make executable
65    #[cfg(unix)]
66    {
67        use std::os::unix::fs::PermissionsExt;
68        let mut perms = tokio::fs::metadata(&cargo_path).await?.permissions();
69        perms.set_mode(0o755);
70        tokio::fs::set_permissions(&cargo_path, perms).await?;
71    }
72
73    Ok(())
74}
75
76async fn install_clippy_config() -> Result<()> {
77    // Copy our strict clippy.toml to the home directory
78    let home_dir = dirs::home_dir()
79        .ok_or_else(|| crate::Error::config("Could not find home directory"))?;
80    
81    let clippy_config = include_str!("../../templates/clippy.toml");
82    let clippy_path = home_dir.join(".clippy.toml");
83    tokio::fs::write(&clippy_path, clippy_config).await?;
84
85    Ok(())
86}
87
88async fn install_shell_integration() -> Result<()> {
89    // Add Ferrous Forge to PATH and setup completion
90    let home_dir = dirs::home_dir()
91        .ok_or_else(|| crate::Error::config("Could not find home directory"))?;
92    
93    let shell_config = format!(
94        r#"
95# Ferrous Forge - Rust Development Standards Enforcer
96export PATH="$HOME/.local/bin:$PATH"
97
98# Enable Ferrous Forge for all Rust development
99export FERROUS_FORGE_ENABLED=1
100"#
101    );
102
103    // Add to common shell config files
104    for shell_file in &[".bashrc", ".zshrc", ".profile"] {
105        let shell_path = home_dir.join(shell_file);
106        if shell_path.exists() {
107            let mut contents = tokio::fs::read_to_string(&shell_path).await?;
108            if !contents.contains("Ferrous Forge") {
109                contents.push_str(&shell_config);
110                tokio::fs::write(&shell_path, contents).await?;
111            }
112        }
113    }
114
115    Ok(())
116}