code.gitea.io/gitea@v1.21.7/build/generate-go-licenses.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  //go:build ignore
     5  
     6  package main
     7  
     8  import (
     9  	"encoding/json"
    10  	"fmt"
    11  	"io/fs"
    12  	"os"
    13  	"path"
    14  	"path/filepath"
    15  	"regexp"
    16  	"sort"
    17  	"strings"
    18  
    19  	"code.gitea.io/gitea/modules/container"
    20  )
    21  
    22  // regexp is based on go-license, excluding README and NOTICE
    23  // https://github.com/google/go-licenses/blob/master/licenses/find.go
    24  var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)
    25  
    26  type LicenseEntry struct {
    27  	Name        string `json:"name"`
    28  	Path        string `json:"path"`
    29  	LicenseText string `json:"licenseText"`
    30  }
    31  
    32  func main() {
    33  	if len(os.Args) != 3 {
    34  		fmt.Println("usage: go run generate-go-licenses.go <base-dir> <out-json-file>")
    35  		os.Exit(1)
    36  	}
    37  
    38  	base, out := os.Args[1], os.Args[2]
    39  
    40  	// Add ext for excluded files because license_test.go will be included for some reason.
    41  	// And there are more files that should be excluded, check with:
    42  	//
    43  	// go run github.com/google/go-licenses@v1.6.0 save . --force --save_path=.go-licenses 2>/dev/null
    44  	// find .go-licenses -type f | while read FILE; do echo "${$(basename $FILE)##*.}"; done | sort -u
    45  	//    AUTHORS
    46  	//    COPYING
    47  	//    LICENSE
    48  	//    Makefile
    49  	//    NOTICE
    50  	//    gitignore
    51  	//    go
    52  	//    md
    53  	//    mod
    54  	//    sum
    55  	//    toml
    56  	//    txt
    57  	//    yml
    58  	//
    59  	// It could be removed once we have a better regex.
    60  	excludedExt := container.SetOf(".gitignore", ".go", ".mod", ".sum", ".toml", ".yml")
    61  
    62  	var paths []string
    63  	err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
    64  		if err != nil {
    65  			return err
    66  		}
    67  		if entry.IsDir() || !licenseRe.MatchString(entry.Name()) || excludedExt.Contains(filepath.Ext(entry.Name())) {
    68  			return nil
    69  		}
    70  		paths = append(paths, path)
    71  		return nil
    72  	})
    73  	if err != nil {
    74  		panic(err)
    75  	}
    76  
    77  	sort.Strings(paths)
    78  
    79  	var entries []LicenseEntry
    80  	for _, filePath := range paths {
    81  		licenseText, err := os.ReadFile(filePath)
    82  		if err != nil {
    83  			panic(err)
    84  		}
    85  
    86  		pkgPath := filepath.ToSlash(filePath)
    87  		pkgPath = strings.TrimPrefix(pkgPath, base+"/")
    88  		pkgName := path.Dir(pkgPath)
    89  
    90  		// There might be a bug somewhere in go-licenses that sometimes interprets the
    91  		// root package as "." and sometimes as "code.gitea.io/gitea". Workaround by
    92  		// removing both of them for the sake of stable output.
    93  		if pkgName == "." || pkgName == "code.gitea.io/gitea" {
    94  			continue
    95  		}
    96  
    97  		entries = append(entries, LicenseEntry{
    98  			Name:        pkgName,
    99  			Path:        pkgPath,
   100  			LicenseText: string(licenseText),
   101  		})
   102  	}
   103  
   104  	jsonBytes, err := json.MarshalIndent(entries, "", "  ")
   105  	if err != nil {
   106  		panic(err)
   107  	}
   108  
   109  	// Ensure file has a final newline
   110  	if jsonBytes[len(jsonBytes)-1] != '\n' {
   111  		jsonBytes = append(jsonBytes, '\n')
   112  	}
   113  
   114  	err = os.WriteFile(out, jsonBytes, 0o644)
   115  	if err != nil {
   116  		panic(err)
   117  	}
   118  }