aenvs/internal/cli/init.go

177 lines
4.0 KiB
Go

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
}