go.uber.org/cadence@v1.2.9/internal/cmd/tools/copyright/licensegen.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package main
    22  
    23  import (
    24  	"bufio"
    25  	"flag"
    26  	"fmt"
    27  	"io"
    28  	"io/ioutil"
    29  	"os"
    30  	"path/filepath"
    31  	"strings"
    32  )
    33  
    34  type (
    35  	// task that adds license header to source
    36  	// files, if they don't already exist
    37  	addLicenseHeaderTask struct {
    38  		license string  // license header string to add
    39  		config  *config // root directory of the project source
    40  	}
    41  
    42  	// command line config params
    43  	config struct {
    44  		rootDir    string
    45  		verifyOnly bool
    46  	}
    47  )
    48  
    49  // licenseFileName is the name of the license file
    50  const licenseFileName = "LICENSE"
    51  
    52  // unique indicator that identifies a license header
    53  const licenseHeaderIndicator = "Copyright (c)"
    54  
    55  var (
    56  	// directories to be excluded
    57  	dirExcludeList = []string{"vendor/", "idls/"}
    58  	// default perms for the newly created files
    59  	defaultFilePerms = os.FileMode(0644)
    60  )
    61  
    62  // command line utility that adds license header
    63  // to the source files. Usage as follows:
    64  //
    65  //	./cmd/tools/copyright/licensegen.go
    66  func main() {
    67  
    68  	var cfg config
    69  	flag.StringVar(&cfg.rootDir, "rootDir", ".", "project root directory")
    70  	flag.BoolVar(&cfg.verifyOnly, "verifyOnly", false,
    71  		"don't automatically add headers, just verify all files")
    72  	flag.Parse()
    73  
    74  	task := newAddLicenseHeaderTask(&cfg)
    75  	if err := task.run(); err != nil {
    76  		fmt.Println(err)
    77  		os.Exit(-1)
    78  	}
    79  }
    80  
    81  func newAddLicenseHeaderTask(cfg *config) *addLicenseHeaderTask {
    82  	return &addLicenseHeaderTask{
    83  		config: cfg,
    84  	}
    85  }
    86  
    87  func (task *addLicenseHeaderTask) run() error {
    88  	data, err := ioutil.ReadFile(task.config.rootDir + "/" + licenseFileName)
    89  	if err != nil {
    90  		return fmt.Errorf("error reading license file, errr=%v", err.Error())
    91  	}
    92  
    93  	task.license = string(data)
    94  
    95  	err = filepath.Walk(task.config.rootDir, task.handleFile)
    96  	if err != nil {
    97  		return fmt.Errorf("copyright header check failed, err=%v", err.Error())
    98  	}
    99  	return nil
   100  }
   101  
   102  func (task *addLicenseHeaderTask) handleFile(path string, fileInfo os.FileInfo, err error) error {
   103  
   104  	if err != nil {
   105  		return err
   106  	}
   107  
   108  	if fileInfo.IsDir() {
   109  		return nil
   110  	}
   111  
   112  	if !mustProcessPath(path) {
   113  		return nil
   114  	}
   115  
   116  	if !strings.HasSuffix(fileInfo.Name(), ".go") {
   117  		return nil
   118  	}
   119  
   120  	f, err := os.Open(path)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	reader := bufio.NewReader(f)
   126  	firstLine, err := reader.ReadString('\n')
   127  	f.Close()
   128  
   129  	if err != nil && !isEOF(err) {
   130  		return err
   131  	}
   132  
   133  	if strings.Contains(firstLine, licenseHeaderIndicator) {
   134  		return nil // file already has the copyright header
   135  	}
   136  
   137  	// at this point, src file is missing the header
   138  	if task.config.verifyOnly {
   139  		if !isFileAutogenerated(path) {
   140  			return fmt.Errorf("%v missing license header", path)
   141  		}
   142  	}
   143  
   144  	data, err := ioutil.ReadFile(path)
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	return ioutil.WriteFile(path, []byte(task.license+string(data)), defaultFilePerms)
   150  }
   151  
   152  func isFileAutogenerated(path string) bool {
   153  	return strings.HasPrefix(path, ".gen")
   154  }
   155  
   156  func mustProcessPath(path string) bool {
   157  	for _, d := range dirExcludeList {
   158  		if strings.HasPrefix(path, d) {
   159  			return false
   160  		}
   161  	}
   162  	return true
   163  }
   164  
   165  // returns true if the error type is an EOF
   166  func isEOF(err error) bool {
   167  	return err == io.EOF || err == io.ErrUnexpectedEOF
   168  }