package cli import ( "bufio" "fmt" "os" "path/filepath" "strings" "github.com/spf13/cobra" "github.com/user/aevs/internal/config" "github.com/user/aevs/internal/scanner" ) var ( initForce bool ) var initCmd = &cobra.Command{ Use: "init [project-name]", Short: "Initialize project configuration", Long: `Initialize aevs.yaml configuration in the current directory.`, Args: cobra.MaximumNArgs(1), RunE: runInit, } func init() { initCmd.Flags().BoolVarP(&initForce, "force", "f", false, "overwrite existing aevs.yaml") } func runInit(cmd *cobra.Command, args []string) error { configPath := config.DefaultProjectConfigFile // Check if config already exists configExists := false if _, err := os.Stat(configPath); err == nil { configExists = true } // Scan for env files fmt.Println() fmt.Println("Scanning for env files...") fmt.Println() currentDir, err := os.Getwd() if err != nil { return fmt.Errorf("failed to get current directory: %w", err) } envFiles, err := scanner.Scan(currentDir) if err != nil { return fmt.Errorf("failed to scan directory: %w", err) } if len(envFiles) == 0 { fmt.Println("Warning: No env files found.") fmt.Println() fmt.Println("You can add files manually to aevs.yaml later.") return nil } // Handle existing config if configExists && !initForce { fmt.Printf("Project already initialized in %s\n", configPath) fmt.Println("Scanning for new env files...") fmt.Println() // Load existing config existingCfg, err := config.LoadProjectConfig(configPath) if err != nil { return fmt.Errorf("failed to load existing config: %w", err) } // Find new files newFiles := findNewFiles(envFiles, existingCfg.Files) if len(newFiles) == 0 { fmt.Println("No new files found.") return nil } fmt.Printf("Found %d new file(s):\n", len(newFiles)) for _, file := range newFiles { fmt.Printf(" + %s\n", file) } fmt.Println() // Ask to add reader := bufio.NewReader(os.Stdin) fmt.Print("Add to aevs.yaml? [Y/n]: ") answer, _ := reader.ReadString('\n') answer = strings.TrimSpace(strings.ToLower(answer)) if answer == "n" || answer == "no" { return nil } // Add new files existingCfg.Files = append(existingCfg.Files, newFiles...) // Save updated config if err := config.SaveProjectConfig(configPath, existingCfg); err != nil { return fmt.Errorf("failed to save config: %w", err) } fmt.Println() fmt.Println("Updated aevs.yaml") return nil } // Create new config fmt.Printf("Found %d env file(s):\n", len(envFiles)) for _, file := range envFiles { fmt.Printf(" ✓ %s\n", file) } fmt.Println() // Determine project name projectName := "" if len(args) > 0 { projectName = args[0] } else { // Use current directory name projectName = filepath.Base(currentDir) projectName = strings.ToLower(projectName) // Clean up project name (replace invalid chars with -) projectName = strings.Map(func(r rune) rune { if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' || r == '_' { return r } return '-' }, projectName) } // Validate project name if err := config.ValidateProjectName(projectName); err != nil { return err } // Create config cfg := &config.ProjectConfig{ Project: projectName, Files: envFiles, } // Save config if err := config.SaveProjectConfig(configPath, cfg); err != nil { return fmt.Errorf("failed to save config: %w", err) } fmt.Printf("Created aevs.yaml for project %q\n", projectName) fmt.Println() fmt.Println("Next steps:") fmt.Println(" 1. Review aevs.yaml") fmt.Println(" 2. Run 'aevs push' to upload files") return nil } // findNewFiles returns files that are in scanned but not in existing func findNewFiles(scanned, existing []string) []string { existingMap := make(map[string]bool) for _, file := range existing { existingMap[file] = true } var newFiles []string for _, file := range scanned { if !existingMap[file] { newFiles = append(newFiles, file) } } return newFiles }