diff --git a/internal/boilersuite/regexes.go b/internal/boilersuite/regexes.go index d1e6d68..d289299 100644 --- a/internal/boilersuite/regexes.go +++ b/internal/boilersuite/regexes.go @@ -21,11 +21,14 @@ import ( ) var ( - // YearMarkerRegex matches the marker which should appear in boilerplate sample files but not in actual files - YearMarkerRegex = regexp.MustCompile(`<>`) + // CopyrightMarker should appear in boilerplate sample files but not in actual files + CopyrightMarker = "Copyright <>" - // AuthorMarkerRegex matches the marker which should appear in boilerplate sample files but not in actual files - AuthorMarkerRegex = regexp.MustCompile(`<>`) + // YearMarker should appear in boilerplate sample files but not in actual files + YearMarker = "<>" + + // AuthorMarker should appear in boilerplate sample files but not in actual files + AuthorMarker = "<>" // DateRegex matches the actual date found inside a file DateRegex = regexp.MustCompile(`Copyright 20\d\d`) diff --git a/internal/boilersuite/template.go b/internal/boilersuite/template.go index 25e8523..9414d8b 100644 --- a/internal/boilersuite/template.go +++ b/internal/boilersuite/template.go @@ -18,6 +18,7 @@ package boilersuite import ( "fmt" + "os" "strings" ) @@ -46,15 +47,15 @@ type BoilerplateTemplateConfiguration struct { // NewBoilerplateTemplate creates a new boilerplate template using the given raw template and configuration func NewBoilerplateTemplate(raw string, config BoilerplateTemplateConfiguration) (BoilerplateTemplate, error) { - if !YearMarkerRegex.MatchString(raw) { - return BoilerplateTemplate{}, fmt.Errorf("invalid template: couldn't find year replacement marker %s", YearMarkerRegex.String()) + if !strings.Contains(raw, YearMarker) { + return BoilerplateTemplate{}, fmt.Errorf("couldn't find replacement marker %q", YearMarker) } - if !AuthorMarkerRegex.MatchString(raw) { - return BoilerplateTemplate{}, fmt.Errorf("invalid template: couldn't find author replacement marker %s", AuthorMarkerRegex.String()) + if !strings.Contains(raw, AuthorMarker) { + return BoilerplateTemplate{}, fmt.Errorf("couldn't find replacement marker %q", AuthorMarker) } - replaced := AuthorMarkerRegex.ReplaceAllString(raw, config.ExpectedAuthor) + replaced := strings.ReplaceAll(raw, AuthorMarker, config.ExpectedAuthor) lineCount := strings.Count(replaced, "\n") + 1 @@ -66,13 +67,18 @@ func NewBoilerplateTemplate(raw string, config BoilerplateTemplateConfiguration) }, nil } -// Validate checks the given raw input file against the template -func (t BoilerplateTemplate) Validate(raw string) error { - if SkipFileRegex.MatchString(raw) || GeneratedRegex.MatchString(raw) { +// Validate checks the given file path against the template +func (t BoilerplateTemplate) Validate(path string) error { + contents, err := os.ReadFile(path) + if err != nil { + return fmt.Errorf("failed to read: %w", err) + } + + if SkipFileRegex.Match(contents) || GeneratedRegex.Match(contents) { return nil } - normalizedContents, err := t.normalizeAndTrimFile(raw) + normalizedContents, err := t.normalizeAndTrimFile(string(contents)) if err != nil { return err } @@ -96,7 +102,7 @@ func (t BoilerplateTemplate) normalizeAndTrimFile(raw string) (string, error) { } // replace anything which looks like a date with the year marker - raw = DateRegex.ReplaceAllString(raw, "Copyright "+YearMarkerRegex.String()) + raw = DateRegex.ReplaceAllString(raw, CopyrightMarker) // Remove any windows-style line feeds in the raw input diff --git a/main.go b/main.go index 19b67df..1d49d6c 100644 --- a/main.go +++ b/main.go @@ -37,10 +37,6 @@ const ( defaultAuthor = "cert-manager" ) -var ( - alwaysSkippedDirs = []string{".git", "_bin", "bin", "node_modules", "vendor", "third_party", "staging"} -) - //go:embed boilerplate-templates/*.boilertmpl var boilerplateTemplateDir embed.FS @@ -49,7 +45,7 @@ func main() { verboseLogger := log.New(io.Discard, "", 0) skipFlag := flag.String("skip", "", "Space-separated list of prefixes for paths which shouldn't be checked. Spaces in prefixes not supported.") - authorFlag := flag.String("author", defaultAuthor, fmt.Sprintf("The expected author for files, which will be substituted for the %q marker in templates", boilersuite.AuthorMarkerRegex)) + authorFlag := flag.String("author", defaultAuthor, fmt.Sprintf("The expected author for files, which will be substituted for the %q marker in templates", boilersuite.AuthorMarker)) verboseFlag := flag.Bool("verbose", false, "If set, prints verbose output") cpuProfile := flag.String("cpuprofile", "", "If set, writes CPU profiling information to the given filename") printVersion := flag.Bool("version", false, "If set, prints the version and exits") @@ -66,14 +62,13 @@ func main() { logger.Fatalf("usage: %s [--version] [--skip \"paths to skip\"] [--author \"example\"] [--verbose] ", os.Args[0]) } - var skippedDirs []string - + skippedDirs := []string{".git", "_bin", "bin", "node_modules", "vendor", "third_party", "staging"} if skipFlag != nil && len(*skipFlag) > 0 { - skippedDirs = strings.Fields(*skipFlag) + skippedDirs = append(skippedDirs, strings.Fields(*skipFlag)...) } if *verboseFlag { - verboseLogger = log.New(os.Stdout, "[VERBOSE] ", log.LstdFlags) + verboseLogger = log.New(os.Stdout, "[VERBOSE] ", log.LstdFlags|log.Lmsgprefix) } if *cpuProfile != "" { @@ -97,29 +92,9 @@ func main() { targetBase := flag.Arg(0) - dir, err := isDir(targetBase) + targets, err := getTargets(targetBase, templates, skippedDirs, verboseLogger) if err != nil { - // couldn't check if the base was a dir or not - logger.Fatalf("target invalid: %s", err) - } - - var targets []target - - if dir { - targets, err = getTargets(targetBase, templates, skippedDirs, verboseLogger) - if err != nil { - logger.Fatalf("failed to list targets in dir %q: %s", targetBase, err.Error()) - } - } else { - contents, err := os.ReadFile(targetBase) - if err != nil { - logger.Fatalf("failed to read %q: %s", targetBase, err.Error()) - } - - targets = []target{target{ - path: targetBase, - contents: string(contents), - }} + logger.Fatalf("failed to list targets in dir %q: %s", targetBase, err.Error()) } if len(targets) == 0 { @@ -128,19 +103,19 @@ func main() { validationErrors := make([]error, 0) - for _, t := range targets { - tmpl, ok := templates.TemplateFor(t.path) + for _, path := range targets { + tmpl, ok := templates.TemplateFor(path) if !ok { panic("failed to get a template for a target which was already processed") } - err := tmpl.Validate(t.contents) + err := tmpl.Validate(path) if err != nil { - validationErrors = append(validationErrors, fmt.Errorf("invalid boilerplate in %q: %w", t.path, err)) + validationErrors = append(validationErrors, fmt.Errorf("invalid boilerplate in %q: %w", path, err)) continue } - verboseLogger.Printf("validated %q successfully", t.path) + verboseLogger.Printf("validated %q successfully", path) } if len(validationErrors) == 0 { @@ -155,26 +130,22 @@ func main() { logger.Fatalln("at least one file had errors") } -type target struct { - path string - contents string -} +func getTargets(targetBase string, templates boilersuite.TemplateMap, skipList []string, verboseLogger *log.Logger) ([]string, error) { + var targets []string -func isDir(path string) (bool, error) { - stat, err := os.Stat(path) + fileInfo, err := os.Stat(targetBase) if err != nil { - return false, err + return nil, err + } + if fileInfo.Mode().IsRegular() { + if _, ok := templates.TemplateFor(targetBase); ok { + targets = append(targets, targetBase) + } + return targets, nil } - - return stat.IsDir(), nil -} - -func getTargets(targetBase string, templates boilersuite.TemplateMap, skippedPrefixes []string, verboseLogger *log.Logger) ([]target, error) { - var targets []target skipMap := make(map[string]struct{}) - - for _, skip := range append(skippedPrefixes, alwaysSkippedDirs...) { + for _, skip := range skipList { skipMap[skip] = struct{}{} } @@ -221,15 +192,7 @@ func getTargets(targetBase string, templates boilersuite.TemplateMap, skippedPre return nil } - contents, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read %q: %w", path, err) - } - - targets = append(targets, target{ - path: path, - contents: string(contents), - }) + targets = append(targets, path) return nil }) diff --git a/templates_test.go b/templates_test.go index 407486b..b885fd1 100644 --- a/templates_test.go +++ b/templates_test.go @@ -51,13 +51,13 @@ func Test_Templates(t *testing.T) { continue } - if !boilersuite.YearMarkerRegex.Match(contents) { - t.Errorf("couldn't find marker %s in %q", boilersuite.YearMarkerRegex.String(), path) + if !strings.Contains(string(contents), boilersuite.YearMarker) { + t.Errorf("couldn't find marker %s in %q", boilersuite.YearMarker, path) continue } - if !boilersuite.AuthorMarkerRegex.Match(contents) { - t.Errorf("couldn't find marker %s in %q", boilersuite.AuthorMarkerRegex.String(), path) + if !strings.Contains(string(contents), boilersuite.AuthorMarker) { + t.Errorf("couldn't find marker %s in %q", boilersuite.AuthorMarker, path) continue }