diff --git a/Cargo.toml b/Cargo.toml index 65d202e..3412ef3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ which = "7.0" # Colors colored = "2.1" +chrono = "0.4.43" [dev-dependencies] tempfile = "3.13" @@ -86,4 +87,4 @@ strip = true [features] default = [] -embedded-gradle = [] # Embed gradle-wrapper.jar in binary (run download-gradle-wrapper.sh first) \ No newline at end of file +embedded-gradle = [] # Embed gradle-wrapper.jar in binary (run download-gradle-wrapper.sh first) diff --git a/src/commands/create.rs b/src/commands/create.rs new file mode 100644 index 0000000..16a0d64 --- /dev/null +++ b/src/commands/create.rs @@ -0,0 +1,241 @@ +use anyhow::{Result, Context, bail}; +use colored::*; +use std::path::{Path, PathBuf}; +use std::fs; +use chrono::Utc; +use crate::templates::TemplateManager; + +// Use Cargo's version macro instead of importing +const WEEVIL_VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub fn create_project( + name: &str, + template: Option<&str>, + path: Option<&str>, + force: bool, + no_init: bool, + dry_run: bool, +) -> Result<()> { + // Validate project name + validate_project_name(name)?; + + // Determine output directory + let output_dir = if let Some(p) = path { + PathBuf::from(p).join(name) + } else { + PathBuf::from(name) + }; + + // Check if directory exists + if output_dir.exists() && !force { + bail!( + "Directory '{}' already exists\nUse --force to overwrite", + output_dir.display() + ); + } + + let template_name = template.unwrap_or("basic"); + + println!("{}", format!("Creating FTC project '{}' with template '{}'...", name, template_name).bright_cyan().bold()); + println!(); + + if dry_run { + println!("{}", "DRY RUN - No files will be created".yellow().bold()); + println!(); + } + + // Load template manager + let template_mgr = TemplateManager::new()?; + + // Verify template exists + if !template_mgr.template_exists(template_name) { + bail!( + "Template '{}' not found\n\nAvailable templates:\n{}", + template_name, + template_mgr.list_templates().join("\n ") + ); + } + + // Prepare template context + let context = TemplateContext { + project_name: name.to_string(), + package_name: name.to_lowercase().replace("-", "").replace("_", ""), + creation_date: Utc::now().to_rfc3339(), + weevil_version: WEEVIL_VERSION.to_string(), + template_name: template_name.to_string(), + }; + + if !dry_run { + // Create output directory + if force && output_dir.exists() { + println!("{}", "⚠ Removing existing directory...".yellow()); + fs::remove_dir_all(&output_dir)?; + } + fs::create_dir_all(&output_dir)?; + + // Extract template + template_mgr.extract_template(template_name, &output_dir, &context)?; + + println!("{}", "✓ Created directory structure".green()); + + // Initialize git repository + if !no_init { + init_git_repository(&output_dir, template_name)?; + } + + println!(); + print_success_message(name, template_name); + } else { + println!("{}", format!("Would create project '{}' using template '{}'", name, template_name).bright_white()); + println!("{}", format!("Output directory: {}", output_dir.display()).bright_white()); + template_mgr.show_template_info(template_name)?; + } + + Ok(()) +} + +pub fn list_templates() -> Result<()> { + let template_mgr = TemplateManager::new()?; + + println!("{}", "Available templates:".bright_cyan().bold()); + println!(); + + for info in template_mgr.get_template_info_all()? { + println!("{}", format!(" {} {}", info.name, if info.is_default { "(default)" } else { "" }).bright_white().bold()); + println!(" {}", info.description); + println!(" Files: {} | Lines: ~{}", info.file_count, info.line_count); + if info.test_count > 0 { + println!(" Tests: {} tests", info.test_count); + } + println!(); + } + + println!("Use: weevil create --template