From fe6503620a884df9aa326d426e17999d11fe3601 Mon Sep 17 00:00:00 2001 From: Yaroslav Skopets Date: Tue, 28 Apr 2020 15:10:31 +0200 Subject: [PATCH 1/2] add support for .licenserignore files --- README.md | 4 +- pkg/command/verify.go | 4 +- pkg/processor/processor.go | 47 +++++++++++--- pkg/processor/processor_test.go | 61 +++++++++++++++++++ pkg/processor/testdata/.gitignore | 2 + pkg/processor/testdata/.licenserignore | 2 + pkg/processor/testdata/gitignore/.gitignore | 2 + pkg/processor/testdata/gitignore/ignore.yaml | 0 pkg/processor/testdata/gitignore/include.yaml | 0 .../testdata/gitignore/nested/ignore.yaml | 0 .../testdata/gitignore/nested/include.yaml | 0 .../testdata/licenserignore/.licenserignore | 2 + .../testdata/licenserignore/ignore.yaml | 0 .../testdata/licenserignore/include.yaml | 0 .../licenserignore/nested/ignore.yaml | 0 .../licenserignore/nested/include.yaml | 0 16 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 pkg/processor/processor_test.go create mode 100644 pkg/processor/testdata/.gitignore create mode 100644 pkg/processor/testdata/.licenserignore create mode 100644 pkg/processor/testdata/gitignore/.gitignore create mode 100644 pkg/processor/testdata/gitignore/ignore.yaml create mode 100644 pkg/processor/testdata/gitignore/include.yaml create mode 100644 pkg/processor/testdata/gitignore/nested/ignore.yaml create mode 100644 pkg/processor/testdata/gitignore/nested/include.yaml create mode 100644 pkg/processor/testdata/licenserignore/.licenserignore create mode 100644 pkg/processor/testdata/licenserignore/ignore.yaml create mode 100644 pkg/processor/testdata/licenserignore/include.yaml create mode 100644 pkg/processor/testdata/licenserignore/nested/ignore.yaml create mode 100644 pkg/processor/testdata/licenserignore/nested/include.yaml diff --git a/README.md b/README.md index d464344..fed22d6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,9 @@ Licenser will also automatically ignore the following files: - *.md, *.golden - .gitignore -- Anything matched by the top level .gitignore (experimental) +- Files that should be ignored according to .gitignore (experimental) +- .licenserignore +- Files that should be ignored according to .licenserignore (experimental) ## Install diff --git a/pkg/command/verify.go b/pkg/command/verify.go index a4f340e..30a536a 100644 --- a/pkg/command/verify.go +++ b/pkg/command/verify.go @@ -32,7 +32,9 @@ var verifyCmd = &cobra.Command{ Verify will ignore the following files: - *.md, *.golden - .gitignore - - Anything matched by the top level .gitignore (experimental) + - Files that should be ignored according to .gitignore (experimental) + - .licenserignore + - Files that should be ignored according to .licenserignore (experimental) `, Run: func(cmd *cobra.Command, args []string) { license := license.NewApache20(time.Now().Year(), "") diff --git a/pkg/processor/processor.go b/pkg/processor/processor.go index 35a96f1..5fbc8a0 100644 --- a/pkg/processor/processor.go +++ b/pkg/processor/processor.go @@ -27,6 +27,9 @@ import ( "github.com/liamawhite/licenser/pkg/license" ) +// licenserignoreFile is a name for *ignore files specific to licenser. +const licenserignoreFile = ".licenserignore" + // Processor finds all valid files and passes them to a file mutator to be handled type Processor struct { startDirectory string @@ -38,18 +41,20 @@ type Processor struct { dryRun bool success bool - skipListGitIgnore gitignore.GitIgnore - skipListExtension map[string]bool + skipListGitIgnore gitignore.GitIgnore + skipListLicenserIgnore gitignore.GitIgnore + skipListExtension map[string]bool } // New creates a new file processor starting the the passed startDirectory // and using the passed license to apply and verify files func New(startDirectory string, license license.Handler) *Processor { return &Processor{ - startDirectory: startDirectory, - mutator: mutator.New(license), - skipListGitIgnore: buildGitIgnoreSkip(startDirectory), - skipListExtension: buildExtensionSkip(), + startDirectory: startDirectory, + mutator: mutator.New(license), + skipListGitIgnore: buildGitIgnoreSkip(startDirectory), + skipListLicenserIgnore: buildLicenserIgnoreSkip(startDirectory), + skipListExtension: buildExtensionSkip(), } } @@ -111,17 +116,32 @@ func (p *Processor) visit(path string, f os.FileInfo, err error) error { } func (p *Processor) shouldSkip(path string) bool { + // skip predefined file types if _, ok := p.skipListExtension[filepath.Ext(path)]; ok { return true } + // skip .git/**, .gitignore, .gitattributes, etc if strings.Contains(path, ".git") { return true } - f, err := os.Stat(path) - if err != nil { + // don't skip start dir (it cannot be ignored by *ignore files anyway, + // and `go-gitignore` library crashes on this use case) + if path == p.startDirectory { return false } - return p.skipListGitIgnore.Relative(path, f.IsDir()) != nil + // skip according to .gitignore + if match := p.skipListGitIgnore.Match(path); match != nil && match.Ignore() { + return true + } + // skip .licenserignore + if filepath.Base(path) == licenserignoreFile { + return true + } + // skip according to .licenserignore + if match := p.skipListLicenserIgnore.Match(path); match != nil && match.Ignore() { + return true + } + return false } func buildGitIgnoreSkip(startDirectory string) gitignore.GitIgnore { @@ -131,6 +151,15 @@ func buildGitIgnoreSkip(startDirectory string) gitignore.GitIgnore { } return gitignore } + +func buildLicenserIgnoreSkip(startDirectory string) gitignore.GitIgnore { + ignore, err := gitignore.NewRepositoryWithFile(startDirectory, licenserignoreFile) + if err != nil { + fmt.Fprintf(os.Stderr, "error reading contents of %s:%v\n", licenserignoreFile, err) + } + return ignore +} + func buildExtensionSkip() map[string]bool { return map[string]bool{ ".md": true, diff --git a/pkg/processor/processor_test.go b/pkg/processor/processor_test.go new file mode 100644 index 0000000..8dfe36a --- /dev/null +++ b/pkg/processor/processor_test.go @@ -0,0 +1,61 @@ +// Copyright 2020 Tetrate +// +// Licensed 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 processor + +import ( + "fmt" + "path/filepath" + "testing" + + "github.com/liamawhite/licenser/pkg/license" + + "github.com/stretchr/testify/assert" +) + +func Test_shouldSkip(t *testing.T) { + tests := []struct { + path string + want bool + }{ + // never ignore root dir + {".", false}, + + // ignore *ignore files themselves + {".gitignore", true}, + {".gitattributes", true}, + {".licenserignore", true}, + + // ignore according to .licenserignore files + {"licenserignore/ignore.yaml", true}, + {"licenserignore/include.yaml", false}, + {"licenserignore/nested/ignore.yaml", true}, + {"licenserignore/nested/include.yaml", false}, + + // ignore according to .gitignore files + {"gitignore/ignore.yaml", true}, + {"gitignore/include.yaml", false}, + {"gitignore/nested/ignore.yaml", true}, + {"gitignore/nested/include.yaml", false}, + } + processor := New("testdata", license.NewApache20(2020, "ASF")) + for _, tt := range tests { + tc := tt + name := fmt.Sprintf("shouldSkip %s is %t", tc.path, tc.want) + t.Run(name, func(t *testing.T) { + path := filepath.Clean(filepath.Join("testdata", tc.path)) + assert.Equal(t, tc.want, processor.shouldSkip(path)) + }) + } +} diff --git a/pkg/processor/testdata/.gitignore b/pkg/processor/testdata/.gitignore new file mode 100644 index 0000000..fbda146 --- /dev/null +++ b/pkg/processor/testdata/.gitignore @@ -0,0 +1,2 @@ +/gitignore/*.yaml +!/gitignore/include.yaml diff --git a/pkg/processor/testdata/.licenserignore b/pkg/processor/testdata/.licenserignore new file mode 100644 index 0000000..a04c20c --- /dev/null +++ b/pkg/processor/testdata/.licenserignore @@ -0,0 +1,2 @@ +/licenserignore/*.yaml +!/licenserignore/include.yaml diff --git a/pkg/processor/testdata/gitignore/.gitignore b/pkg/processor/testdata/gitignore/.gitignore new file mode 100644 index 0000000..0abca45 --- /dev/null +++ b/pkg/processor/testdata/gitignore/.gitignore @@ -0,0 +1,2 @@ +/nested/*.yaml +!/nested/include.yaml diff --git a/pkg/processor/testdata/gitignore/ignore.yaml b/pkg/processor/testdata/gitignore/ignore.yaml new file mode 100644 index 0000000..e69de29 diff --git a/pkg/processor/testdata/gitignore/include.yaml b/pkg/processor/testdata/gitignore/include.yaml new file mode 100644 index 0000000..e69de29 diff --git a/pkg/processor/testdata/gitignore/nested/ignore.yaml b/pkg/processor/testdata/gitignore/nested/ignore.yaml new file mode 100644 index 0000000..e69de29 diff --git a/pkg/processor/testdata/gitignore/nested/include.yaml b/pkg/processor/testdata/gitignore/nested/include.yaml new file mode 100644 index 0000000..e69de29 diff --git a/pkg/processor/testdata/licenserignore/.licenserignore b/pkg/processor/testdata/licenserignore/.licenserignore new file mode 100644 index 0000000..0abca45 --- /dev/null +++ b/pkg/processor/testdata/licenserignore/.licenserignore @@ -0,0 +1,2 @@ +/nested/*.yaml +!/nested/include.yaml diff --git a/pkg/processor/testdata/licenserignore/ignore.yaml b/pkg/processor/testdata/licenserignore/ignore.yaml new file mode 100644 index 0000000..e69de29 diff --git a/pkg/processor/testdata/licenserignore/include.yaml b/pkg/processor/testdata/licenserignore/include.yaml new file mode 100644 index 0000000..e69de29 diff --git a/pkg/processor/testdata/licenserignore/nested/ignore.yaml b/pkg/processor/testdata/licenserignore/nested/ignore.yaml new file mode 100644 index 0000000..e69de29 diff --git a/pkg/processor/testdata/licenserignore/nested/include.yaml b/pkg/processor/testdata/licenserignore/nested/include.yaml new file mode 100644 index 0000000..e69de29 From f825fdabd1d3f039be6887374218ea50733de3cc Mon Sep 17 00:00:00 2001 From: Yaroslav Skopets Date: Tue, 28 Apr 2020 15:28:57 +0200 Subject: [PATCH 2/2] ci: fix failing build --- ci/lint | 5 ++++- pkg/processor/testdata/gitignore/include.yaml | 13 +++++++++++++ .../testdata/gitignore/nested/include.yaml | 13 +++++++++++++ pkg/processor/testdata/licenserignore/include.yaml | 13 +++++++++++++ .../testdata/licenserignore/nested/include.yaml | 13 +++++++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/ci/lint b/ci/lint index 6605f8b..f64eb6d 100755 --- a/ci/lint +++ b/ci/lint @@ -1,9 +1,12 @@ #!/bin/bash +BASEDIR=$(dirname "$0") +LICENSER="go run ${BASEDIR}/../main.go" + SUCCESS=true # Ensure Licenses are present -if licenser verify -r .; then +if ${LICENSER} verify -r .; then echo "Licenses are present on all recognised files." else echo "Licenses are missing." diff --git a/pkg/processor/testdata/gitignore/include.yaml b/pkg/processor/testdata/gitignore/include.yaml index e69de29..6787f0f 100644 --- a/pkg/processor/testdata/gitignore/include.yaml +++ b/pkg/processor/testdata/gitignore/include.yaml @@ -0,0 +1,13 @@ +# Copyright 2020 Tetrate +# +# Licensed 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. diff --git a/pkg/processor/testdata/gitignore/nested/include.yaml b/pkg/processor/testdata/gitignore/nested/include.yaml index e69de29..6787f0f 100644 --- a/pkg/processor/testdata/gitignore/nested/include.yaml +++ b/pkg/processor/testdata/gitignore/nested/include.yaml @@ -0,0 +1,13 @@ +# Copyright 2020 Tetrate +# +# Licensed 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. diff --git a/pkg/processor/testdata/licenserignore/include.yaml b/pkg/processor/testdata/licenserignore/include.yaml index e69de29..6787f0f 100644 --- a/pkg/processor/testdata/licenserignore/include.yaml +++ b/pkg/processor/testdata/licenserignore/include.yaml @@ -0,0 +1,13 @@ +# Copyright 2020 Tetrate +# +# Licensed 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. diff --git a/pkg/processor/testdata/licenserignore/nested/include.yaml b/pkg/processor/testdata/licenserignore/nested/include.yaml index e69de29..6787f0f 100644 --- a/pkg/processor/testdata/licenserignore/nested/include.yaml +++ b/pkg/processor/testdata/licenserignore/nested/include.yaml @@ -0,0 +1,13 @@ +# Copyright 2020 Tetrate +# +# Licensed 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.