This is an automated email from the ASF dual-hosted git repository.
hufeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-js.git
The following commit(s) were added to refs/heads/master by this push:
new 5e6135b add lint module, it can check notice end year and each file
license
new d12b220 Merge pull request #295 from hufeng/master
5e6135b is described below
commit 5e6135b268aaf3ed4e35125a6d3195f7725154de
Author: hufeng <[email protected]>
AuthorDate: Mon Oct 24 01:07:11 2022 +0800
add lint module, it can check notice end year and each file license
---
.gitignore | 1 +
.husky/pre-commit | 3 +-
Makefile | 4 ++
lint/__license__/.npmignore | 0
lint/__license__/Makefile | 0
lint/__license__/fix.go | 18 +++++
lint/__license__/fix.java | 18 +++++
lint/__license__/fix.js | 18 +++++
Makefile => lint/__license__/fix.sh | 11 +--
lint/__license__/fix.ts | 18 +++++
lint/__license__/fix.xml | 18 +++++
Makefile => lint/__license__/fix.yml | 11 +--
lint/__license__/fix_head.xml | 20 ++++++
lint/__license__/test.go | 1 +
lint/__notice__/NOTICE | 5 ++
lint/__notice__/NOTICE_1 | 1 +
lint/go.mod | 3 +
lint/lint.go | 103 +++++++++++++++++++++++++++
lint/lint_color.go | 35 +++++++++
lint/lint_glob.go | 61 ++++++++++++++++
lint/lint_license.go | 119 +++++++++++++++++++++++++++++++
lint/lint_license_comment.go | 134 +++++++++++++++++++++++++++++++++++
lint/lint_license_test.go | 101 ++++++++++++++++++++++++++
lint/lint_notice.go | 93 ++++++++++++++++++++++++
lint/lint_notice_test.go | 55 ++++++++++++++
lint/main.go | 42 +++++++++++
26 files changed, 871 insertions(+), 22 deletions(-)
diff --git a/.gitignore b/.gitignore
index 8a9083e..e6c0515 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,3 +62,4 @@ examples/hello-egg/typings
examples/hello-midway/src/typings
dubbo-java/nacos-docker/example/standalone-logs/
+dj_lint
diff --git a/.husky/pre-commit b/.husky/pre-commit
index a25a189..ef2f77d 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -2,5 +2,4 @@
. "$(dirname "$0")/_/husky.sh"
npx pretty-quick --staged
-pnpm ts-check
-npm test
+pnpm test
diff --git a/Makefile b/Makefile
index 51ad869..2f3e17e 100644
--- a/Makefile
+++ b/Makefile
@@ -13,6 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+
+build-lint:
+ cd ./lint && go build -o ../dj_lint
+
build-java-demo:
cd ./java/dubbo-demo/dubbo-demo-api && mvn clean package
cd ./java/dubbo-demo/dubbo-demo-api && mvn install
dependency:copy-dependencies
diff --git a/lint/__license__/.npmignore b/lint/__license__/.npmignore
new file mode 100644
index 0000000..e69de29
diff --git a/lint/__license__/Makefile b/lint/__license__/Makefile
new file mode 100644
index 0000000..e69de29
diff --git a/lint/__license__/fix.go b/lint/__license__/fix.go
new file mode 100644
index 0000000..8b3e754
--- /dev/null
+++ b/lint/__license__/fix.go
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
\ No newline at end of file
diff --git a/lint/__license__/fix.java b/lint/__license__/fix.java
new file mode 100644
index 0000000..13e4782
--- /dev/null
+++ b/lint/__license__/fix.java
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ */
+
+public class fix {}
\ No newline at end of file
diff --git a/lint/__license__/fix.js b/lint/__license__/fix.js
new file mode 100644
index 0000000..40b1133
--- /dev/null
+++ b/lint/__license__/fix.js
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ */
+
+console.log('hello')
diff --git a/Makefile b/lint/__license__/fix.sh
similarity index 70%
copy from Makefile
copy to lint/__license__/fix.sh
index 51ad869..5aefc0c 100644
--- a/Makefile
+++ b/lint/__license__/fix.sh
@@ -13,13 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-build-java-demo:
- cd ./java/dubbo-demo/dubbo-demo-api && mvn clean package
- cd ./java/dubbo-demo/dubbo-demo-api && mvn install
dependency:copy-dependencies
- @echo "build java-demo success👏\n"
-
-interpret-jar:build-demo-api
- ts-node ./packages/interpret-cli/src/cli.ts interpret -c dubbo.json
- @echo "interpret-jar success👏\n"
-
-
+echo 'hello'
\ No newline at end of file
diff --git a/lint/__license__/fix.ts b/lint/__license__/fix.ts
new file mode 100644
index 0000000..40b1133
--- /dev/null
+++ b/lint/__license__/fix.ts
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ */
+
+console.log('hello')
diff --git a/lint/__license__/fix.xml b/lint/__license__/fix.xml
new file mode 100644
index 0000000..554ab4c
--- /dev/null
+++ b/lint/__license__/fix.xml
@@ -0,0 +1,18 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+-->
+
+<project></project>
\ No newline at end of file
diff --git a/Makefile b/lint/__license__/fix.yml
similarity index 70%
copy from Makefile
copy to lint/__license__/fix.yml
index 51ad869..95ab194 100644
--- a/Makefile
+++ b/lint/__license__/fix.yml
@@ -13,13 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-build-java-demo:
- cd ./java/dubbo-demo/dubbo-demo-api && mvn clean package
- cd ./java/dubbo-demo/dubbo-demo-api && mvn install
dependency:copy-dependencies
- @echo "build java-demo success👏\n"
-
-interpret-jar:build-demo-api
- ts-node ./packages/interpret-cli/src/cli.ts interpret -c dubbo.json
- @echo "interpret-jar success👏\n"
-
-
+version: 1
diff --git a/lint/__license__/fix_head.xml b/lint/__license__/fix_head.xml
new file mode 100644
index 0000000..111ab91
--- /dev/null
+++ b/lint/__license__/fix_head.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+-->
+
+<project></project>
\ No newline at end of file
diff --git a/lint/__license__/test.go b/lint/__license__/test.go
new file mode 100644
index 0000000..06ab7d0
--- /dev/null
+++ b/lint/__license__/test.go
@@ -0,0 +1 @@
+package main
diff --git a/lint/__notice__/NOTICE b/lint/__notice__/NOTICE
new file mode 100644
index 0000000..45c8ee2
--- /dev/null
+++ b/lint/__notice__/NOTICE
@@ -0,0 +1,5 @@
+Apache Dubbo Js
+Copyright 2018-2021 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/lint/__notice__/NOTICE_1 b/lint/__notice__/NOTICE_1
new file mode 100644
index 0000000..6a686ff
--- /dev/null
+++ b/lint/__notice__/NOTICE_1
@@ -0,0 +1 @@
+Copyright 2018-2022 The Apache Software Foundation
\ No newline at end of file
diff --git a/lint/go.mod b/lint/go.mod
new file mode 100644
index 0000000..c091b29
--- /dev/null
+++ b/lint/go.mod
@@ -0,0 +1,3 @@
+module lint
+
+go 1.18
diff --git a/lint/lint.go b/lint/lint.go
new file mode 100644
index 0000000..fafcb92
--- /dev/null
+++ b/lint/lint.go
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import (
+ "fmt"
+ "os"
+ "regexp"
+ "time"
+)
+
+var (
+ //skip dir
+ rx =
regexp.MustCompile("node_modules|vendor|lib|target|__license__|__notice__|husky")
+ license = NewLicense()
+ // lint notice
+ nl = &NoticeLinter{File: "./NOTICE"}
+ // lint license
+ ll = &LicenseLinter{
+ Dir: "./",
+ g: G{
+ DirFilter: func(path string) bool {
+ return !rx.MatchString(path)
+ },
+ FileFilter: func(path string) bool {
+ return license.support(path)
+ },
+ },
+ }
+)
+
+// fix_one fix single file
+func fix_one(nl *NoticeLinter, ll *LicenseLinter, f string) {
+ now := time.Now()
+
+ if f == "NOTICE" {
+ // fix notice
+ if err := nl.fix(); err != nil {
+ fmt.Fprint(os.Stderr, err)
+ }
+ } else {
+ // fixed license
+ if err := ll.fix_file(f); err != nil {
+ fmt.Fprint(os.Stderr, err)
+ }
+ }
+
+ fmt.Println(warn(fmt.Sprintf("fix cost: %v", time.Since(now))))
+}
+
+// fix_all fix all file
+func fix_all(nl *NoticeLinter, ll *LicenseLinter) {
+ now := time.Now()
+
+ // fix notice
+ if err := nl.fix(); err != nil {
+ fmt.Fprint(os.Stderr, err)
+ }
+
+ // fixed license
+ if err := ll.fix(); err != nil {
+ fmt.Fprint(os.Stderr, err)
+ }
+
+ fmt.Println(warn(fmt.Sprintf("fix cost: %v", time.Since(now))))
+}
+
+//lint lint all file
+func lint(nl *NoticeLinter, ll *LicenseLinter) {
+ now := time.Now()
+
+ // lint mode
+ if err := nl.lint(); err != nil {
+ fmt.Fprintln(os.Stderr, failed(err.Error()))
+ }
+
+ // check license
+ files, err := ll.lint()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, failed(err.Error()))
+ }
+
+ for _, f := range files {
+ fmt.Fprintln(os.Stdout, failed(fmt.Sprintf("%s => lose apache
license", f)))
+ }
+
+ fmt.Println(success(fmt.Sprintf("lint cost: %v", time.Since(now))))
+}
diff --git a/lint/lint_color.go b/lint/lint_color.go
new file mode 100644
index 0000000..629eb3e
--- /dev/null
+++ b/lint/lint_color.go
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import "fmt"
+
+// failed, show red text
+func failed(text string) string {
+ return fmt.Sprintf("\033[91m%s\033[0m", text)
+}
+
+// success, show green text
+func success(text string) string {
+ return fmt.Sprintf("\033[92m%s\033[0m", text)
+}
+
+// warning, show yellow text
+func warn(text string) string {
+ return fmt.Sprintf("\033[93m%s\033[0m", text)
+}
diff --git a/lint/lint_glob.go b/lint/lint_glob.go
new file mode 100644
index 0000000..f1c256b
--- /dev/null
+++ b/lint/lint_glob.go
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import (
+ "io/fs"
+ "path/filepath"
+)
+
+// G is a dir and file filter setting
+type G struct {
+ DirFilter func(root string) bool
+ FileFilter func(root string) bool
+}
+
+// glob files with given filter
+func glob(dir string, g G) ([]string, error) {
+ var files []string
+
+ err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err
error) error {
+ if err != nil {
+ return err
+ }
+
+ if d.IsDir() {
+ // skip dir
+ if g.DirFilter != nil && !g.DirFilter(path) {
+ return filepath.SkipDir
+ }
+ return nil
+ }
+
+ // collect files
+ if g.FileFilter != nil && g.FileFilter(path) {
+ files = append(files, path)
+ }
+
+ return nil
+ })
+
+ if err != nil {
+ return nil, err
+ }
+
+ return files, nil
+}
diff --git a/lint/lint_license.go b/lint/lint_license.go
new file mode 100644
index 0000000..1bc44be
--- /dev/null
+++ b/lint/lint_license.go
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "path/filepath"
+ "strings"
+ "sync"
+)
+
+type LicenseLinter struct {
+ Dir string
+ g G
+}
+
+func (l *LicenseLinter) lint() ([]string, error) {
+ var errFiles []string
+ // glob files
+ files, err := glob(l.Dir, l.g)
+ if err != nil {
+ return nil, err
+ }
+
+ // check license
+ var wg sync.WaitGroup
+ ch := make(chan string)
+
+ for _, f := range files {
+ wg.Add(1)
+ go func(f string) {
+ defer wg.Done()
+ b, err := ioutil.ReadFile(f)
+ if err != nil {
+ panic(err)
+ }
+ if !strings.Contains(string(b),
"http://www.apache.org/licenses/LICENSE-2.0") {
+ ch <- f
+ }
+ }(f)
+ }
+
+ go func() {
+ wg.Wait()
+ close(ch)
+ }()
+
+ for s := range ch {
+ errFiles = append(errFiles, s)
+ }
+
+ return errFiles, nil
+}
+
+func (l *LicenseLinter) fix() error {
+ var wg sync.WaitGroup
+ files, err := l.lint()
+ if err != nil {
+ return err
+ }
+
+ for _, f := range files {
+ wg.Add(1)
+ go func(f string) {
+ defer wg.Done()
+ err := l.fix_file(f)
+ if err != nil {
+ panic(err)
+ }
+ }(f)
+ }
+
+ wg.Wait()
+ return nil
+}
+
+func (l *LicenseLinter) fix_file(f string) error {
+ if !license.support(f) {
+ return nil
+ }
+
+ // read file
+ b, err := ioutil.ReadFile(f)
+ if err != nil {
+ panic(err)
+ }
+ s := string(b)
+
+ // xml with header
+ ext := filepath.Ext(f)
+ x := `<?xml version="1.0" encoding="UTF-8"?>`
+ if ext == ".xml" && strings.Contains(s, x) {
+ nx := strings.Replace(s, x, x+"\n\n"+license.get(f)+"\n\n", 1)
+ ioutil.WriteFile(f, []byte(nx), 0644)
+ } else {
+ // common
+ err = ioutil.WriteFile(f, []byte(fmt.Sprintf("%s\n\n%s",
license.get(f), b)), 0644)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/lint/lint_license_comment.go b/lint/lint_license_comment.go
new file mode 100644
index 0000000..c37ef74
--- /dev/null
+++ b/lint/lint_license_comment.go
@@ -0,0 +1,134 @@
+package main
+
+import (
+ "path/filepath"
+ "strings"
+)
+
+// ~~~~~~~~~~~~~~~~~~~~ define each license ~~~~~~~~~~~~~~~~~~~~
+var common = `
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ */
+`
+
+var sh = `
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF 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.
+`
+
+var xml = `
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+-->
+`
+
+// ~~~~~~~~~~~~~~~~ end ~~~~~~~~~~~~~~~~
+
+var (
+ lic License
+ supportedFileNames = []string{"Makefile", ".npmignore"}
+)
+
+type License map[string]string
+
+// init license
+func NewLicense() License {
+ // cache license
+ if lic != nil {
+ return lic
+ }
+
+ // make license
+ license := make(map[string]string)
+ license[".go"] = strings.TrimSpace(common)
+ license[".py"] = strings.TrimSpace(sh)
+ license[".sh"] = strings.TrimSpace(sh)
+ license[".yml"] = strings.TrimSpace(sh)
+ license[".yaml"] = strings.TrimSpace(sh)
+ license[".ts"] = strings.TrimSpace(common)
+ license[".java"] = strings.TrimSpace(common)
+ license[".js"] = strings.TrimSpace(common)
+ license["Makefile"] = strings.TrimSpace(sh)
+ license[".npmignore"] = strings.TrimSpace(sh)
+ license[".xml"] = strings.TrimSpace(xml)
+
+ return license
+}
+
+// support check current file is supported with license
+func (l License) support(file string) bool {
+ // check file name
+ for _, name := range supportedFileNames {
+ if file == name {
+ return true
+ }
+ }
+
+ // check file suffix
+ for suffix := range l {
+ if strings.HasSuffix(file, suffix) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// get license by file and ext name
+func (l License) get(file string) string {
+ // check file name
+ for _, name := range supportedFileNames {
+ if file == name {
+ return l[name]
+ }
+ }
+
+ // check file
+ for suffix, license := range l {
+ ext := filepath.Ext(file)
+ if ext == suffix {
+ return license
+ }
+ }
+
+ return ""
+}
diff --git a/lint/lint_license_test.go b/lint/lint_license_test.go
new file mode 100644
index 0000000..9188bb4
--- /dev/null
+++ b/lint/lint_license_test.go
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import (
+ "errors"
+ "io/ioutil"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func TestLicenseLinter_glob(t *testing.T) {
+ f, err := glob("./__license__", G{
+ FileFilter: func(root string) bool {
+ return filepath.Ext(root) == ".go"
+ },
+ })
+
+ if err != nil {
+ t.Fatalf("glob error: %v", err)
+ }
+
+ if len(f) == 0 {
+ t.Fatalf("glob error: %v", errors.New("no files"))
+ }
+}
+
+func TestLicenseLinter_lint(t *testing.T) {
+ l := LicenseLinter{
+ Dir: "./__license__",
+ g: G{
+ FileFilter: func(root string) bool {
+ return filepath.Ext(root) == ".go"
+ },
+ },
+ }
+
+ files, err := l.lint()
+ if err != nil {
+ t.Fatalf("lint error: %v", err)
+ }
+
+ if len(files) == 0 {
+ t.Fatalf("lint error: %v", files)
+ }
+}
+
+func TestLicenseLinter_fix(t *testing.T) {
+ // write test data
+ ioutil.WriteFile("./__license__/fix.go", []byte("package main"), 0644)
+ ioutil.WriteFile("./__license__/fix.js",
[]byte("console.log('hello');"), 0644)
+ ioutil.WriteFile("./__license__/fix.ts",
[]byte("console.log('hello');"), 0644)
+ ioutil.WriteFile("./__license__/fix.sh", []byte("echo 'hello'"), 0644)
+ ioutil.WriteFile("./__license__/fix.yml", []byte(`version: 1`), 0644)
+ ioutil.WriteFile("./__license__/Makefile", []byte(``), 0644)
+ ioutil.WriteFile("./__license__/.npmignore", []byte(``), 0644)
+ ioutil.WriteFile("./__license__/fix.java", []byte(`public class fix
{}`), 0644)
+ ioutil.WriteFile("./__license__/fix.xml",
[]byte(`<project></project>`), 0644)
+ ioutil.WriteFile("./__license__/fix_head.xml", []byte(`<?xml
version="1.0" encoding="UTF-8"?><project></project>`), 0644)
+
+ l := &LicenseLinter{
+ Dir: "./__license__",
+ g: G{
+ FileFilter: func(root string) bool {
+ return strings.Contains(root, "fix")
+ },
+ },
+ }
+
+ err := l.fix()
+ if err != nil {
+ t.Fatalf("fix error: %v", err)
+ }
+
+ // read test data
+ files, err := l.lint()
+ if err != nil {
+ t.Fatalf("lint error: %v", err)
+ }
+
+ // check file
+ if len(files) != 0 {
+ t.Fatalf("lint error: %v", files)
+ }
+}
diff --git a/lint/lint_notice.go b/lint/lint_notice.go
new file mode 100644
index 0000000..3019567
--- /dev/null
+++ b/lint/lint_notice.go
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// NoticeLinter check notice file end year
+type NoticeLinter struct {
+ File string
+}
+
+func parseYear(file string) (string, error) {
+ // read notice file
+ b, err := ioutil.ReadFile(file)
+ if err != nil {
+ return "", fmt.Errorf("read %s error %s", file, err)
+ }
+
+ // find match date-range string
+ re := regexp.MustCompile(`2018-(\d{4})`)
+ g := re.FindStringSubmatch(string(b))
+ if len(g) == 0 {
+ return "", fmt.Errorf("match date-range error")
+ }
+
+ // return end year
+ return g[1], nil
+}
+
+func (n *NoticeLinter) lint() error {
+ y, err := parseYear(n.File)
+ if err != nil {
+ return err
+ }
+
+ // convert
+ v, err := strconv.Atoi(y)
+ if err != nil {
+ return err
+ }
+
+ // lint
+ year := time.Now().Year()
+ if v != year {
+ return fmt.Errorf("NOTICE file err => end year %d != %d", v,
year)
+ }
+
+ return nil
+}
+
+func (n *NoticeLinter) fix() error {
+ // parse end year
+ y, err := parseYear(n.File)
+ if err != nil {
+ return err
+ }
+
+ // read file content
+ b, err := ioutil.ReadFile(n.File)
+ if err != nil {
+ return err
+ }
+
+ // replace with current year
+ s := strings.Replace(string(b), y, strconv.Itoa(time.Now().Year()),
0644)
+ if err := ioutil.WriteFile(n.File, []byte(s), 0644); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/lint/lint_notice_test.go b/lint/lint_notice_test.go
new file mode 100644
index 0000000..457999c
--- /dev/null
+++ b/lint/lint_notice_test.go
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import (
+ "io/ioutil"
+ "testing"
+)
+
+func TestNoticeLinter_lint(t *testing.T) {
+ l := NoticeLinter{
+ File: "./__notice__/NOTICE",
+ }
+ err := l.lint()
+ if err == nil {
+ t.Fatalf("lint error")
+ }
+}
+
+func TestNoticeLinter_fixed(t *testing.T) {
+ // write test data
+ ioutil.WriteFile("./__notice__/NOTICE_1", []byte("Copyright 2018-2021
The Apache Software Foundation"), 0644)
+
+ // init notice linter
+ l := NoticeLinter{
+ File: "./__notice__/NOTICE_1",
+ }
+
+ // fixed notice
+ err := l.fix()
+ if err != nil {
+ t.Fatalf("fixed error")
+ }
+
+ // check notice
+ err = l.lint()
+ if err != nil {
+ t.Fatalf("lint error")
+ }
+}
diff --git a/lint/main.go b/lint/main.go
new file mode 100644
index 0000000..d814798
--- /dev/null
+++ b/lint/main.go
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 main
+
+import (
+ "flag"
+)
+
+var (
+ fix = flag.String("fix", "", "fix mode")
+)
+
+func main() {
+ flag.Parse()
+
+ switch *fix {
+ case "":
+ // lint all files
+ lint(nl, ll)
+ case "all":
+ // fix all files
+ fix_all(nl, ll)
+ default:
+ // fix single file
+ fix_one(nl, ll, *fix)
+ }
+}