diff --git a/Makefile b/Makefile index ed013f9..1c7dffa 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ APP=addlicense GROUP=devops REVISION="" -VERSION=1.1.1$(REVISION) +VERSION=1.1.2$(REVISION) DOCKER_REGISTRY=harbor.avroid.tech all: diff --git a/main.go b/main.go index bee76c4..a6c2dd5 100644 --- a/main.go +++ b/main.go @@ -37,9 +37,9 @@ Flags: ` var ( - skipExtensionFlags stringSlice - ignorePatterns stringSlice - spdx spdxFlag + skipExtensionFlags stringSlice + ignorePatterns stringSlice + spdx spdxFlag holder = flag.String("c", "Avroid, Ltd.", "copyright holder") license = flag.String("l", "commercial", "license type: commercial, apache, bsd, mit, mpl") @@ -156,10 +156,19 @@ func main() { log.Printf("%s: %v", f.path, err) return err } + hasCorrectAvroidLicense, err := fileHasCorrectAvroidLicense(f.path, data) + if err != nil { + log.Printf("%s: %v", f.path, err) + return err + } if !hasLicense { - fmt.Printf("%s\n", f.path) + fmt.Printf("%s: missing license header\n", f.path) return errors.New("missing license header") } + if !hasCorrectAvroidLicense { + fmt.Printf("%s: incorrect year in license header\n", f.path) + return errors.New("incorrect year in license header") + } } else { modified, err := addLicense(f.path, f.mode, t, data) if err != nil { @@ -267,6 +276,17 @@ func fileHasLicense(path string) (bool, error) { return hasLicense(b) || isGenerated(b), nil } +// fileHasLicense reports whether the file at path contains a correct Avroid license header. +func fileHasCorrectAvroidLicense(path string, data licenseData) (bool, error) { + b, err := ioutil.ReadFile(path) + if err != nil { + return false, err + } + // If generated, we count it as if it has a license. + return hasCorrectAvroidLicense(b, data), nil +} + +// licenseHeader populates the provided license template with data, and returns // licenseHeader populates the provided license template with data, and returns // it with the proper prefix for the file type specified by path. The file does // not need to actually exist, only its name is used to determine the prefix. @@ -276,9 +296,9 @@ func licenseHeader(path string, tmpl *template.Template, data licenseData) ([]by base := strings.ToLower(filepath.Base(path)) switch fileExtension(base) { - case ".c", ".h", ".gv", ".java", ".scala", ".kt", ".kts": + case ".c", ".h", ".gv", ".java", ".scala", ".kt", ".kts", ".qml": lic, err = executeTemplate(tmpl, data, "/*", " * ", " */") - case ".js", ".mjs", ".cjs", ".jsx", ".tsx", ".css", ".scss", ".sass", ".ts": + case ".js", ".mjs", ".cjs", ".jsx", ".tsx", ".css", ".scss", ".sass": lic, err = executeTemplate(tmpl, data, "/**", " * ", " */") case ".cc", ".cpp", ".cs", ".go", ".hcl", ".hh", ".hpp", ".m", ".mm", ".proto", ".rs", ".swift", ".dart", ".groovy", ".v", ".sv": lic, err = executeTemplate(tmpl, data, "", "// ", "") @@ -290,7 +310,7 @@ func licenseHeader(path string, tmpl *template.Template, data licenseData) ([]by lic, err = executeTemplate(tmpl, data, "", "% ", "") case ".hs", ".sql", ".sdl": lic, err = executeTemplate(tmpl, data, "", "-- ", "") - case ".html", ".xml", ".vue", ".wxi", ".wxl", ".wxs": + case ".html", ".xml", ".vue", ".wxi", ".wxl", ".wxs", ".qrc": lic, err = executeTemplate(tmpl, data, "") case ".php": lic, err = executeTemplate(tmpl, data, "", "// ", "") @@ -298,11 +318,19 @@ func licenseHeader(path string, tmpl *template.Template, data licenseData) ([]by lic, err = executeTemplate(tmpl, data, "{#", "", "#}") case ".ml", ".mli", ".mll", ".mly": lic, err = executeTemplate(tmpl, data, "(**", " ", "*)") + case ".ts": + lic, err = executeTemplate(tmpl, data, "/**", " * ", " */") + if err != nil { + lic, err = executeTemplate(tmpl, data, "") + } default: // handle various cmake files if base == "cmakelists.txt" || strings.HasSuffix(base, ".cmake.in") || strings.HasSuffix(base, ".cmake") { lic, err = executeTemplate(tmpl, data, "", "# ", "") } + if base == "Jenkinsfile" || strings.HasSuffix(base, ".groovy") { + lic, err = executeTemplate(tmpl, data, "", "// ", "") + } } return lic, err } @@ -357,11 +385,23 @@ func isGenerated(b []byte) bool { } func hasLicense(b []byte) bool { - n := 1000 - if len(b) < 1000 { + n := 500 + if len(b) < 500 { n = len(b) } return bytes.Contains(bytes.ToLower(b[:n]), []byte("copyright")) || bytes.Contains(bytes.ToLower(b[:n]), []byte("mozilla public")) || bytes.Contains(bytes.ToLower(b[:n]), []byte("spdx-license-identifier")) } + +func hasCorrectAvroidLicense(b []byte, data licenseData) bool { + n := 500 + if len(b) < 500 { + n = len(b) + } + if bytes.Contains(bytes.ToLower(b[:n]), []byte("avroid, ltd. written permission")) { + return bytes.Contains(bytes.ToLower(b[:n]), []byte(fmt.Sprintf("copyright (c) avroid, ltd., %s", data.Year))) + } + + return true +} diff --git a/tmpl.go b/tmpl.go index 83da7f2..7130ed4 100644 --- a/tmpl.go +++ b/tmpl.go @@ -89,7 +89,7 @@ func executeTemplate(t *template.Template, d licenseData, top, mid, bot string) return out.Bytes(), nil } -const tmplCommercial = `Copyright {{.Holder}} {{ if .Year }} 2023-{{.Year}}{{ end }} +const tmplCommercial = `Copyright {{.Holder}} {{ if .Year }} {{.Year}}{{ end }} You can not use the contents of the file in any way without AVROID, Ltd. written permission.