package config import ( "fmt" "os" "regexp" "gopkg.in/yaml.v3" ) // ProjectConfig represents ./aevs.yaml type ProjectConfig struct { Project string `yaml:"project"` // unique project identifier Files []string `yaml:"files"` // list of file paths to sync } // projectNameRegex validates project names (only a-z, 0-9, -, _) var projectNameRegex = regexp.MustCompile(`^[a-z0-9_-]+$`) // LoadProjectConfig loads a project config from the specified path func LoadProjectConfig(path string) (*ProjectConfig, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } var cfg ProjectConfig if err := yaml.Unmarshal(data, &cfg); err != nil { return nil, err } // Validate project name if err := ValidateProjectName(cfg.Project); err != nil { return nil, err } return &cfg, nil } // SaveProjectConfig saves a project config to the specified path func SaveProjectConfig(path string, cfg *ProjectConfig) error { // Validate project name before saving if err := ValidateProjectName(cfg.Project); err != nil { return err } // Marshal to YAML data, err := yaml.Marshal(cfg) if err != nil { return err } // Write file if err := os.WriteFile(path, data, 0644); err != nil { return err } return nil } // ValidateProjectName checks if the project name contains only a-z, 0-9, -, _ func ValidateProjectName(name string) error { if name == "" { return fmt.Errorf("project name cannot be empty") } if !projectNameRegex.MatchString(name) { return fmt.Errorf("invalid project name %q; use only a-z, 0-9, -, _", name) } return nil }