177 lines
4.0 KiB
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
|
|
}
|