dev
diff --git a/.licenserc.json b/.licenserc.json
new file mode 100644
index 0000000..3d262cc
--- /dev/null
+++ b/.licenserc.json
@@ -0,0 +1,48 @@
+{
+ "licenseStrict": [
+ "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."
+ ],
+ "licenseLoose": [
+ "Apache License",
+ "Version 2.0"
+ ],
+ "targetFiles": [
+ "java",
+ "go",
+ "py",
+ "sh",
+ "graphql",
+ "yaml",
+ "yml"
+ ],
+ "exclude": {
+ "files": [
+ ".gitignore",
+ "NOTICE",
+ "go.mod",
+ "go.sum"
+ ],
+ "extensions": [
+ "md",
+ "xml",
+ "json"
+ ],
+ "directories": [
+ "bin",
+ ".github",
+ ".git",
+ ".idea"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4e83903
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,69 @@
+# Copyright © 2020 Hoshea Jiang <hoshea@apache.org>
+#
+# 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.
+
+PROJECT = license-checker
+VERSION ?= latest
+OUT_DIR = bin
+CURDIR := $(shell pwd)
+FILES := $$(find .$$($(PACKAGE_DIRECTORIES)) -name "*.go")
+FAIL_ON_STDOUT := awk '{ print } END { if (NR > 0) { exit 1 } }'
+
+GO := GO111MODULE=on go
+GO_PATH = $$($(GO) env GOPATH)
+GO_BUILD = $(GO) build
+GO_GET = $(GO) get
+GO_TEST = $(GO) test
+GO_LINT = $(GO_PATH)/bin/golangci-lint
+GO_LICENSER = $(GO_PATH)/bin/go-licenser
+
+# Ensure GOPATH is set before running build process.
+ifeq "$(GOPATH)" ""
+ $(error Please set the environment variable GOPATH before running `make`)
+endif
+
+all: clean deps lint test build
+
+tools:
+ mkdir -p $(GO_PATH)/bin
+ $(GO_LINT) version || curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GO_PATH)/bin v1.21.0
+ $(GO_LICENSER) -version || GO111MODULE=off $(GO_GET) -u github.com/elastic/go-licenser
+
+deps: tools
+ $(GO_GET) -v -t -d ./...
+
+.PHONY: lint
+lint: tools
+ @gofmt -s -l -w $(FILES) 2>&1 | $(FAIL_ON_STDOUT)
+ $(GO_LINT) run -v ./...
+
+.PHONE: test
+test: clean lint
+ $(GO_TEST) ./...
+ @>&2 echo "Great, all tests passed."
+
+.PHONY: build
+build: deps
+ $(GO_BUILD) -o $(OUT_DIR)/$(PROJECT)
+
+#.PHONY: license
+#license: clean tools
+# $(GO_LICENSER) -d -license='ASL2' .
+
+.PHONY: fix
+fix: tools
+ $(GO_LINT) run -v --fix ./...
+
+.PHONY: clean
+clean: tools
+ -rm -rf bin
diff --git a/cmd/root.go b/cmd/root.go
index 14c62b6..841fa46 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -1,5 +1,5 @@
/*
-Copyright © 2020 NAME HERE <EMAIL ADDRESS>
+Copyright © 2020 Hoshea Jiang <hoshea@apache.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,23 +16,33 @@
package cmd
import (
+ "encoding/json"
"fmt"
"github.com/spf13/cobra"
+ "io/ioutil"
+ "license-checker/util"
"os"
-
- homedir "github.com/mitchellh/go-homedir"
- "github.com/spf13/viper"
+ "path/filepath"
)
var cfgFile string
+var checkPath string
+var loose bool
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
- Use: "license-checker",
- Short: "A brief description of your application",
-
+ Use: "license-checker [flags]",
+ Long: `license-checker walks the specified path recursively and checks
+if the specified files have the license header in the config file.`,
Run: func(cmd *cobra.Command, args []string) {
- fmt.Println("Hello Cobra CLI!")
+ config, err := LoadConfig()
+ if err != nil {
+ fmt.Println(err)
+ }
+ //fmt.Println(config.TargetFiles)
+ if err := Walk(checkPath, config); err != nil {
+ fmt.Println(err)
+ }
},
}
@@ -46,41 +56,77 @@
}
func init() {
- cobra.OnInitialize(initConfig)
-
- // Here you will define your flags and configuration settings.
- // Cobra supports persistent flags, which, if defined here,
- // will be global for your application.
-
- rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.license-checker.yaml)")
-
- // Cobra also supports local flags, which will only run
- // when this action is called directly.
- rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+ rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", ".licenserc.json", "the config file")
+ rootCmd.PersistentFlags().StringVarP(&checkPath, "path", "p", "", "the path to check (required)")
+ rootCmd.PersistentFlags().BoolVarP(&loose, "loose", "l", false, "loose mode")
+ if err := rootCmd.MarkPersistentFlagRequired("path"); err != nil {
+ fmt.Println(err)
+ }
}
-// initConfig reads in config file and ENV variables if set.
-func initConfig() {
- if cfgFile != "" {
- // Use config file from the flag.
- viper.SetConfigFile(cfgFile)
- } else {
- // Find home directory.
- home, err := homedir.Dir()
+type excludeConfig struct {
+ Files []string `json:"files"`
+ Extensions []string `json:"extensions"`
+ Directories []string `json:"directories"`
+}
+
+type Config struct {
+ LicenseStrict []string `json:"licenseStrict"`
+ LicenseLoose []string `json:"licenseLoose"`
+ TargetFiles []string `json:"targetFiles"`
+ Exclude excludeConfig `json:"exclude"`
+}
+
+type Result struct {
+ Success []string `json:"success"`
+ Failure []string `json:"failure"`
+}
+
+// LoadConfig reads in config file.
+func LoadConfig() (*Config, error) {
+ var config Config
+ bytes, err := ioutil.ReadFile(cfgFile)
+ if err != nil {
+ return nil, err
+ }
+
+ err = json.Unmarshal(bytes, &config)
+ if err != nil {
+ return nil, err
+ }
+
+ return &config, nil
+}
+
+func Walk(p string, cfg *Config) error {
+ inExcludeDir := util.InStrSliceMapKeyFunc(cfg.Exclude.Directories)
+ inExcludeExt := util.InStrSliceMapKeyFunc(cfg.Exclude.Extensions)
+ inExcludeFiles := util.InStrSliceMapKeyFunc(cfg.Exclude.Files)
+
+ err := filepath.Walk(p, func(path string, fi os.FileInfo, err error) error {
if err != nil {
- fmt.Println(err)
- os.Exit(1)
+ fmt.Println(err) // can't walk here,
+ return nil // but continue walking elsewhere
}
- // Search config in home directory with name ".license-checker" (without extension).
- viper.AddConfigPath(home)
- viper.SetConfigName(".license-checker")
- }
+ if fi.IsDir() {
+ if inExcludeDir(fi.Name()) {
+ return filepath.SkipDir
+ }
+ } else {
+ ext := util.GetFileExtension(fi.Name())
+ if inExcludeFiles(fi.Name()) || inExcludeExt(ext) {
+ return nil
+ }
- viper.AutomaticEnv() // read in environment variables that match
+ // TODO: open the file and check
+ fmt.Println(path)
+ //curDir := strings.Replace(path, fi.Name(), "", 1)
+ //fmt.Println(curDir)
+ }
- // If a config file is found, read it in.
- if err := viper.ReadInConfig(); err == nil {
- fmt.Println("Using config file:", viper.ConfigFileUsed())
- }
+ return nil
+ })
+
+ return err
}
diff --git a/config.json b/config.json
deleted file mode 100644
index 10d2446..0000000
--- a/config.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "**/*.{java, go, py}": [
- "You can put multiline headers like this",
- "Copyright Foo, Inc. and other Bar contributors.",
- "Permission is hereby granted, free of charge, to any person obtaining a",
- "copy of this software and associated documentation files (the",
- "\"Software\"), to deal in the Software without restriction, including",
- "without limitation the rights to use, copy, modify, merge, publish,",
- "distribute, sublicense, and/or sell copies of the Software, and to permit",
- "persons to whom the Software is furnished to do so, subject to the",
- "following conditions:",
- "..."
- ],
-
- "ignore": [
- "lib/vendor/jquery.js", // ignore this file
- "vendor/" // ignore all files under vendor
- ]
-}
\ No newline at end of file
diff --git a/config.yaml b/config.yaml
deleted file mode 100644
index 4845d7a..0000000
--- a/config.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-include:
-
-exclude:
\ No newline at end of file
diff --git a/main.go b/main.go
index d2e9d49..e9f9be6 100644
--- a/main.go
+++ b/main.go
@@ -1,5 +1,5 @@
/*
-Copyright © 2020 NAME HERE <EMAIL ADDRESS>
+Copyright © 2020 Hoshea Jiang <hoshea@apache.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/test/testcase.go b/test/testcase.go
new file mode 100644
index 0000000..4020ef8
--- /dev/null
+++ b/test/testcase.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 test
diff --git a/test/testcase.java b/test/testcase.java
new file mode 100644
index 0000000..43a94f3
--- /dev/null
+++ b/test/testcase.java
@@ -0,0 +1,14 @@
+// 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.
diff --git a/test/testcase.md b/test/testcase.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/testcase.md
diff --git a/test/testcase3.py b/test/testcase3.py
new file mode 100644
index 0000000..a9fd83f
--- /dev/null
+++ b/test/testcase3.py
@@ -0,0 +1,16 @@
+#
+# 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.
+#
\ No newline at end of file
diff --git a/util/str.go b/util/str.go
new file mode 100644
index 0000000..b953e48
--- /dev/null
+++ b/util/str.go
@@ -0,0 +1,43 @@
+/*
+Copyright © 2020 Hoshea Jiang <hoshea@apache.org>
+
+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 util
+
+import (
+ "strings"
+)
+
+func InStrSliceMapKeyFunc(strs []string) func(string) bool {
+ set := make(map[string]struct{})
+
+ for _, e := range strs {
+ set[e] = struct{}{}
+ }
+
+ return func(s string) bool {
+ _, ok := set[s]
+ return ok
+ }
+}
+
+func GetFileExtension(filename string) string {
+ i := strings.LastIndex(filename, ".")
+ if i != -1 {
+ if i+1 < len(filename) {
+ return filename[i+1:]
+ }
+ }
+ return ""
+}
diff --git a/util/str_test.go b/util/str_test.go
new file mode 100644
index 0000000..fce8965
--- /dev/null
+++ b/util/str_test.go
@@ -0,0 +1,58 @@
+/*
+Copyright © 2020 Hoshea Jiang <hoshea@apache.org>
+
+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 util
+
+import "testing"
+
+func TestGetFileExtension(t *testing.T) {
+ type args struct {
+ filename string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "txt extension",
+ args: args{
+ filename: ".abc.txt",
+ },
+ want: "txt",
+ },
+ {
+ name: "no file extensions",
+ args: args{
+ filename: ".abc.txt.",
+ },
+ want: "",
+ },
+ {
+ name: "no file extensions",
+ args: args{
+ filename: "lkjsdl",
+ },
+ want: "",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := GetFileExtension(tt.args.filename); got != tt.want {
+ t.Errorf("GetFileExtension() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}