Skip to content

Commit

Permalink
Add support for the Elastic license (#15)
Browse files Browse the repository at this point in the history
* Add support for the Elastic license

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 <[email protected]>
  • Loading branch information
exekias authored Aug 3, 2018
1 parent 813c09e commit 0232478
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 59 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ Usage: go-licenser [flags] [path]
Options:
-d skips rewriting files and returns exitcode 1 if any discrepancies are found.
-exclude value
path to exclude (can be specified multiple times).
-ext string
sets the file extension to scan for. (default ".go")
-license string
sets the license type to check: ASL2, Elastic (default "ASL2")
```

## Contributing
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 ./...
6 changes: 6 additions & 0 deletions fixtures/x-pack/doc.testdata
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions fixtures/x-pack/wrong.testdata
Original file line number Diff line number Diff line change
@@ -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
17 changes: 0 additions & 17 deletions golden/excludedpath/file.go
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions golden/x-pack/doc.go
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions golden/x-pack/wrong.go
Original file line number Diff line number Diff line change
@@ -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
83 changes: 50 additions & 33 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -42,6 +43,7 @@ const (
exitFailedToWalkPath
exitFailedToOpenWalkFile
errFailedRewrittingFile
errUnknownLicense
)

var usageText = `
Expand All @@ -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"}
)
Expand All @@ -102,25 +111,33 @@ 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: ASL2, 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() != "<nil>" {
fmt.Fprint(os.Stderr, err)
}

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("unknown 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]
Expand All @@ -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) {
Expand All @@ -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 {
Expand All @@ -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
}

Expand All @@ -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
}
Expand All @@ -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
}

Expand Down
54 changes: 47 additions & 7 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package main
import (
"bytes"
"crypto/sha1"
"errors"
"flag"
"fmt"
"io"
Expand Down Expand Up @@ -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
Expand All @@ -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,
},
Expand All @@ -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("unknown 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,
},
Expand All @@ -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
Expand All @@ -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)
}
}
Expand Down

0 comments on commit 0232478

Please sign in to comment.