diff --git a/addlicense/main.go b/addlicense/main.go index c0e8963..59a2150 100644 --- a/addlicense/main.go +++ b/addlicense/main.go @@ -53,7 +53,7 @@ Flags: var ( skipExtensionFlags stringSlice ignorePatterns stringSlice - spdx spdxFlag + spdx SpdxFlag holder = flag.String("c", "Google LLC", "copyright holder") license = flag.String("l", "apache", "license type: apache, bsd, mit, mpl") @@ -85,22 +85,22 @@ func (i *stringSlice) Set(value string) error { return nil } -// spdxFlag defines the line flag behavior for specifying SPDX support. -type spdxFlag string +// SpdxFlag defines the line flag behavior for specifying SPDX support. +type SpdxFlag string const ( - spdxOff spdxFlag = "" - spdxOn spdxFlag = "true" // value set by flag package on bool flag - spdxOnly spdxFlag = "only" + spdxOff SpdxFlag = "" + spdxOn SpdxFlag = "true" // value set by flag package on bool flag + spdxOnly SpdxFlag = "only" ) // IsBoolFlag causes a bare '-s' flag to be set as the string 'true'. This // allows the use of the bare '-s' or setting a string '-s=only'. -func (i *spdxFlag) IsBoolFlag() bool { return true } -func (i *spdxFlag) String() string { return string(*i) } +func (i *SpdxFlag) IsBoolFlag() bool { return true } +func (i *SpdxFlag) String() string { return string(*i) } -func (i *spdxFlag) Set(value string) error { - v := spdxFlag(value) +func (i *SpdxFlag) Set(value string) error { + v := SpdxFlag(value) if v != spdxOn && v != spdxOnly { return fmt.Errorf("error: flag 's' expects '%v' or '%v'", spdxOn, spdxOnly) } @@ -180,7 +180,7 @@ func validatePatterns(patterns []string) error { // Run executes addLicense with supplied variables func Run( ignorePatternList []string, - spdx spdxFlag, + spdx SpdxFlag, license LicenseData, licenseFileOverride string, // Provide a file to use as the license header verbose bool, @@ -453,5 +453,6 @@ func hasLicense(b []byte) bool { } 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")) + bytes.Contains(bytes.ToLower(b[:n]), []byte("spdx-license-identifier")) || + bytes.Contains(bytes.ToLower(b[:n]), []byte("©")) } diff --git a/addlicense/main_test.go b/addlicense/main_test.go index bc5f098..ae79d6c 100644 --- a/addlicense/main_test.go +++ b/addlicense/main_test.go @@ -407,6 +407,7 @@ func TestHasLicense(t *testing.T) { {"Subject to the terms of the Mozilla Public License", true}, {"SPDX-License-Identifier: MIT", true}, {"spdx-license-identifier: MIT", true}, + {"© 2000 Acme Inc.", true}, } for _, tt := range tests { diff --git a/addlicense/tmpl.go b/addlicense/tmpl.go index 8eba269..6646657 100644 --- a/addlicense/tmpl.go +++ b/addlicense/tmpl.go @@ -50,7 +50,7 @@ type LicenseData struct { // optional templateFile. If templateFile is provided, the license is read // from the specified file. Otherwise, a template is loaded for the specified // license, if recognized. -func fetchTemplate(license string, templateFile string, spdx spdxFlag) (string, error) { +func fetchTemplate(license string, templateFile string, spdx SpdxFlag) (string, error) { var t string if spdx == spdxOnly { t = tmplSPDX diff --git a/addlicense/tmpl_test.go b/addlicense/tmpl_test.go index 93635cc..56c8e74 100644 --- a/addlicense/tmpl_test.go +++ b/addlicense/tmpl_test.go @@ -34,7 +34,7 @@ func TestFetchTemplate(t *testing.T) { description string // test case description license string // license passed to fetchTemplate templateFile string // templatefile passed to fetchTemplate - spdx spdxFlag // spdx value passed to fetchTemplate + spdx SpdxFlag // spdx value passed to fetchTemplate wantTemplate string // expected returned template wantErr error // expected returned error }{ diff --git a/cmd/headers.go b/cmd/headers.go index 7cae659..8ba6578 100644 --- a/cmd/headers.go +++ b/cmd/headers.go @@ -97,6 +97,29 @@ config, see the "copywrite init" command.`, SPDXID: conf.Project.License, } + // By default force addlicense's SDPX template + var useSPDX addlicense.SpdxFlag = "only" + + // If custom license template is configured, create a temporary file + // and write template to it + licenseFile := "" + if conf.Project.LicenseTemplate != "" { + errMsg := "Failed to create a temporary file for custom license template: %v\n\n" + if f, e := os.CreateTemp("", "copywrite-custom-license.tpl"); e == nil { + licenseFile = f.Name() + useSPDX = "" // Don't force SPDX template in case of custom template + defer os.Remove(f.Name()) + if _, e := f.WriteString(conf.Project.LicenseTemplate); e != nil { + cmd.Print(text.FgRed.Sprintf(errMsg, e)) + return + } + f.Close() + } else { + cmd.Print(text.FgRed.Sprintf(errMsg, e)) + return + } + } + verbose := true // Wrap hclogger to use standard lib's log.Logger @@ -113,7 +136,7 @@ config, see the "copywrite init" command.`, // return a non-zero error code. gha.StartGroup("The following files are missing headers:") - err := addlicense.Run(ignoredPatterns, "only", licenseData, "", verbose, plan, []string{"."}, stdcliLogger) + err := addlicense.Run(ignoredPatterns, useSPDX, licenseData, licenseFile, verbose, plan, []string{"."}, stdcliLogger) gha.EndGroup() cobra.CheckErr(err) diff --git a/config/config.go b/config/config.go index 1b70f03..68962dc 100644 --- a/config/config.go +++ b/config/config.go @@ -29,6 +29,7 @@ type Project struct { CopyrightHolder string `koanf:"copyright_holder"` HeaderIgnore []string `koanf:"header_ignore"` License string `koanf:"license"` + LicenseTemplate string `koanf:"license_template"` // Upstream is optional and only used if a given repo pulls from another Upstream string `koanf:"upstream"`