package app import ( "fmt" "sort" "strings" "gitea.maximumdirect.net/eric/narratio/internal/config" ) type artifactSelectionFlag struct { values []string } func (f *artifactSelectionFlag) String() string { return strings.Join(f.values, ",") } func (f *artifactSelectionFlag) Set(value string) error { f.values = append(f.values, value) return nil } func (f *artifactSelectionFlag) Normalize() ([]string, error) { if len(f.values) == 0 { return nil, nil } seen := map[string]struct{}{} out := make([]string, 0, len(f.values)) for _, raw := range f.values { for _, part := range strings.Split(raw, ",") { name := strings.TrimSpace(part) if name == "" { return nil, fmt.Errorf("artifact names must be non-empty") } if _, ok := seen[name]; ok { continue } seen[name] = struct{}{} out = append(out, name) } } sort.Strings(out) return out, nil } func validateSelectedArtifacts(cfg *config.Config, selected []string) error { if len(selected) == 0 { return nil } if cfg == nil || cfg.Pipeline == nil || cfg.Pipeline.Scriptorium == nil { return fmt.Errorf("--artifacts requires pipeline.scriptorium.artifacts to be configured") } configured := cfg.Pipeline.Scriptorium.Artifacts if len(configured) == 0 { return fmt.Errorf("--artifacts requires at least one configured artifact in pipeline.scriptorium.artifacts") } for _, name := range selected { if _, ok := configured[name]; !ok { return fmt.Errorf("--artifacts includes unknown artifact %q", name) } } return nil }