From 49b56ac0571a53360489e5a02f1a01327add3217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20P=C3=A9rez-Aradros=20Herce?= Date: Tue, 31 Jul 2018 18:49:37 +0200 Subject: [PATCH] Add support for the Elastic license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces support for multiple licenses, keeping the current one (`ASL2`) as the default, and adding an `Elastic` option. Signed-off-by: Carlos PĂ©rez-Aradros Herce --- Makefile | 2 +- appveyor.yml | 2 +- fixtures/x-pack/doc.testdata | 6 +++ fixtures/x-pack/wrong.testdata | 18 ++++++++ golden/excludedpath/file.go | 17 ------- golden/x-pack/doc.go | 6 +++ golden/x-pack/wrong.go | 18 ++++++++ main.go | 83 ++++++++++++++++++++-------------- main_test.go | 54 +++++++++++++++++++--- 9 files changed, 147 insertions(+), 59 deletions(-) create mode 100644 fixtures/x-pack/doc.testdata create mode 100644 fixtures/x-pack/wrong.testdata create mode 100644 golden/x-pack/doc.go create mode 100644 golden/x-pack/wrong.go diff --git a/Makefile b/Makefile index 9efa865..954abf0 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ install: lint: deps build @ golint -set_exit_status $(shell go list ./...) @ gofmt -d -e -s $(LINT_FOLDERS) - @ ./bin/go-licenser -d + @ ./bin/go-licenser -d -exclude golden .PHONY: format format: deps build diff --git a/appveyor.yml b/appveyor.yml index 257e52f..2292bcb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,5 +34,5 @@ build_script: - go install github.com/elastic/go-licenser test_script: - - go-licenser -d + - go-licenser -d -exclude golden - go test -timeout 10s -p 4 -race -cover ./... diff --git a/fixtures/x-pack/doc.testdata b/fixtures/x-pack/doc.testdata new file mode 100644 index 0000000..73c6292 --- /dev/null +++ b/fixtures/x-pack/doc.testdata @@ -0,0 +1,6 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +// Package testdata holds test data for the licensing cmd +package testdata diff --git a/fixtures/x-pack/wrong.testdata b/fixtures/x-pack/wrong.testdata new file mode 100644 index 0000000..03724a5 --- /dev/null +++ b/fixtures/x-pack/wrong.testdata @@ -0,0 +1,18 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package testdata diff --git a/golden/excludedpath/file.go b/golden/excludedpath/file.go index 30e3706..2168920 100644 --- a/golden/excludedpath/file.go +++ b/golden/excludedpath/file.go @@ -1,19 +1,2 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you under -// the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - // Package excludedpath holds test data for the licensing cmd package excludedpath diff --git a/golden/x-pack/doc.go b/golden/x-pack/doc.go new file mode 100644 index 0000000..73c6292 --- /dev/null +++ b/golden/x-pack/doc.go @@ -0,0 +1,6 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +// Package testdata holds test data for the licensing cmd +package testdata diff --git a/golden/x-pack/wrong.go b/golden/x-pack/wrong.go new file mode 100644 index 0000000..03724a5 --- /dev/null +++ b/golden/x-pack/wrong.go @@ -0,0 +1,18 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package testdata diff --git a/main.go b/main.go index a6e35ee..2581289 100644 --- a/main.go +++ b/main.go @@ -29,9 +29,10 @@ import ( ) const ( - defaultExt = ".go" - defaultPath = "." - defaultFormat = "%s: is missing the license header\n" + defaultExt = ".go" + defaultPath = "." + defaultLicense = "ASL2" + defaultFormat = "%s: is missing the license header\n" ) const ( @@ -42,6 +43,7 @@ const ( exitFailedToWalkPath exitFailedToOpenWalkFile errFailedRewrittingFile + errUnknownLicense ) var usageText = ` @@ -54,31 +56,38 @@ Options: `[1:] -// Header is the licenser that all of the files in the repository must have. -var Header = []string{ - `// Licensed to Elasticsearch B.V. under one or more contributor`, - `// license agreements. See the NOTICE file distributed with`, - `// this work for additional information regarding copyright`, - `// ownership. Elasticsearch B.V. licenses this file to you under`, - `// the Apache License, Version 2.0 (the "License"); you may`, - `// not use this file except in compliance with the License.`, - `// You may obtain a copy of the License at`, - `//`, - `// http://www.apache.org/licenses/LICENSE-2.0`, - `//`, - `// Unless required by applicable law or agreed to in writing,`, - `// software distributed under the License is distributed on an`, - `// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY`, - `// KIND, either express or implied. See the License for the`, - `// specific language governing permissions and limitations`, - `// under the License.`, +// Headers is the map of supported licenses +var Headers = map[string][]string{ + "ASL2": { + `// Licensed to Elasticsearch B.V. under one or more contributor`, + `// license agreements. See the NOTICE file distributed with`, + `// this work for additional information regarding copyright`, + `// ownership. Elasticsearch B.V. licenses this file to you under`, + `// the Apache License, Version 2.0 (the "License"); you may`, + `// not use this file except in compliance with the License.`, + `// You may obtain a copy of the License at`, + `//`, + `// http://www.apache.org/licenses/LICENSE-2.0`, + `//`, + `// Unless required by applicable law or agreed to in writing,`, + `// software distributed under the License is distributed on an`, + `// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY`, + `// KIND, either express or implied. See the License for the`, + `// specific language governing permissions and limitations`, + `// under the License.`, + }, + "Elastic": { + `// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one`, + `// or more contributor license agreements. Licensed under the Elastic License;`, + `// you may not use this file except in compliance with the Elastic License.`, + }, } var ( dryRun bool extension string args []string - headerBytes []byte + license string exclude sliceFlag defaultExludedDirs = []string{"vendor", ".git"} ) @@ -102,17 +111,14 @@ func init() { flag.Var(&exclude, "exclude", `path to exclude (can be specified multiple times).`) flag.BoolVar(&dryRun, "d", false, `skips rewriting files and returns exitcode 1 if any discrepancies are found.`) flag.StringVar(&extension, "ext", defaultExt, "sets the file extension to scan for.") + flag.StringVar(&license, "license", defaultLicense, "sets the license type to check: apache2, elastic") flag.Usage = usageFlag flag.Parse() args = flag.Args() - for i := range Header { - headerBytes = append(headerBytes, []byte(Header[i])...) - headerBytes = append(headerBytes, []byte("\n")...) - } } func main() { - err := run(args, exclude, extension, dryRun, os.Stdout) + err := run(args, license, exclude, extension, dryRun, os.Stdout) if err != nil && err.Error() != "" { fmt.Fprint(os.Stderr, err) } @@ -120,7 +126,18 @@ func main() { os.Exit(Code(err)) } -func run(args, exclude []string, ext string, dry bool, out io.Writer) error { +func run(args []string, license string, exclude []string, ext string, dry bool, out io.Writer) error { + header, ok := Headers[license] + if !ok { + return &Error{err: fmt.Errorf("unkown license: %s", license), code: errUnknownLicense} + } + + var headerBytes []byte + for i := range header { + headerBytes = append(headerBytes, []byte(header[i])...) + headerBytes = append(headerBytes, []byte("\n")...) + } + var path = defaultPath if len(args) > 0 { path = args[0] @@ -130,7 +147,7 @@ func run(args, exclude []string, ext string, dry bool, out io.Writer) error { return &Error{err: err, code: exitFailedToStatTree} } - return walk(path, ext, exclude, dry, out) + return walk(path, ext, license, headerBytes, exclude, dry, out) } func reportFile(out io.Writer, f string) { @@ -142,7 +159,7 @@ func reportFile(out io.Writer, f string) { fmt.Fprintf(out, defaultFormat, rel) } -func walk(p, ext string, exclude []string, dry bool, out io.Writer) error { +func walk(p, ext, license string, headerBytes []byte, exclude []string, dry bool, out io.Writer) error { var err error filepath.Walk(p, func(path string, info os.FileInfo, walkErr error) error { if walkErr != nil { @@ -160,7 +177,7 @@ func walk(p, ext string, exclude []string, dry bool, out io.Writer) error { return filepath.SkipDir } - if e := addOrCheckLicense(path, ext, info, dry, out); e != nil { + if e := addOrCheckLicense(path, ext, license, headerBytes, info, dry, out); e != nil { err = e } @@ -170,7 +187,7 @@ func walk(p, ext string, exclude []string, dry bool, out io.Writer) error { return err } -func addOrCheckLicense(path, ext string, info os.FileInfo, dry bool, out io.Writer) error { +func addOrCheckLicense(path, ext, license string, headerBytes []byte, info os.FileInfo, dry bool, out io.Writer) error { if info.IsDir() || filepath.Ext(path) != ext { return nil } @@ -181,7 +198,7 @@ func addOrCheckLicense(path, ext string, info os.FileInfo, dry bool, out io.Writ } defer f.Close() - if licensing.ContainsHeader(f, Header) { + if licensing.ContainsHeader(f, Headers[license]) { return nil } diff --git a/main_test.go b/main_test.go index 69f064f..73a236d 100644 --- a/main_test.go +++ b/main_test.go @@ -20,6 +20,7 @@ package main import ( "bytes" "crypto/sha1" + "errors" "flag" "fmt" "io" @@ -106,6 +107,7 @@ func dcopy(src, dest string, info os.FileInfo) error { func Test_run(t *testing.T) { type args struct { args []string + license string exclude []string ext string dry bool @@ -122,7 +124,8 @@ func Test_run(t *testing.T) { name: "Run a diff prints a list of files that need the license header", args: args{ args: []string{"testdata"}, - exclude: []string{"excludedpath"}, + license: defaultLicense, + exclude: []string{"excludedpath", "x-pack"}, ext: defaultExt, dry: true, }, @@ -137,23 +140,60 @@ testdata/multilevel/sublevel/partial.go: is missing the license header testdata/singlelevel/doc.go: is missing the license header testdata/singlelevel/main.go: is missing the license header testdata/singlelevel/wrapper.go: is missing the license header +`[1:], + }, + { + name: "Run a diff prints a list of files that need the Elastic license header", + args: args{ + args: []string{"testdata"}, + license: "Elastic", + ext: defaultExt, + dry: true, + }, + want: 1, + err: &Error{code: 1}, + wantOutput: ` +testdata/excludedpath/file.go: is missing the license header +testdata/multilevel/doc.go: is missing the license header +testdata/multilevel/main.go: is missing the license header +testdata/multilevel/sublevel/autogen.go: is missing the license header +testdata/multilevel/sublevel/doc.go: is missing the license header +testdata/multilevel/sublevel/partial.go: is missing the license header +testdata/singlelevel/doc.go: is missing the license header +testdata/singlelevel/main.go: is missing the license header +testdata/singlelevel/wrapper.go: is missing the license header +testdata/singlelevel/zrapper.go: is missing the license header +testdata/x-pack/wrong.go: is missing the license header `[1:], }, { name: "Run against an unexisting dir fails", args: args{ - args: []string{"ignore"}, - ext: defaultExt, - dry: false, + args: []string{"ignore"}, + license: defaultLicense, + ext: defaultExt, + dry: false, }, want: 2, err: goosPathError(2, "ignore"), }, + { + name: "Unknown license fails", + args: args{ + args: []string{"ignore"}, + license: "foo", + ext: defaultExt, + dry: false, + }, + want: 7, + err: &Error{err: errors.New("unkown license: foo"), code: 7}, + }, { name: "Run with default mode rewrites the source files", args: args{ args: []string{"testdata"}, - exclude: []string{"excludedpath"}, + license: defaultLicense, + exclude: []string{"excludedpath", "x-pack"}, ext: defaultExt, dry: false, }, @@ -168,7 +208,7 @@ testdata/singlelevel/wrapper.go: is missing the license header } var buf = new(bytes.Buffer) - var err = run(tt.args.args, tt.args.exclude, tt.args.ext, tt.args.dry, buf) + var err = run(tt.args.args, tt.args.license, tt.args.exclude, tt.args.ext, tt.args.dry, buf) if !reflect.DeepEqual(err, tt.err) { t.Errorf("run() error = %v, wantErr %v", err, tt.err) return @@ -188,7 +228,7 @@ testdata/singlelevel/wrapper.go: is missing the license header if tt.wantGolden { if *update { copyFixtures(t, "golden") - if err := run([]string{"golden"}, tt.args.exclude, tt.args.ext, tt.args.dry, buf); err != nil { + if err := run([]string{"golden"}, tt.args.license, tt.args.exclude, tt.args.ext, tt.args.dry, buf); err != nil { t.Fatal(err) } }