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)
+       }
+}

Reply via email to