forked from cilium/cilium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Louis DeLosSantos <louis.delos@isovalent.com>
- Loading branch information
Showing
1 changed file
with
141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2019 Authors of Cilium | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"go/ast" | ||
"go/format" | ||
"go/parser" | ||
"go/token" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
const ( | ||
usage = `spdxconv is a tool for converting Cilium's copyright and license header | ||
to a SPDX compliant one | ||
Usage: | ||
spdxconv [package_dir] - provide spdxconv with a absolute path to the go package you'd like to convert. | ||
` | ||
) | ||
|
||
var ( | ||
// RegexMap maps an identifying regexp expression | ||
// with the SPDX string that replaces it. | ||
RegexpMap = map[*regexp.Regexp]string{ | ||
regexp.MustCompile(`(?m)Apache License, Version 2.0`): "// SPDX-License-Identifier: Apache-2.0", | ||
} | ||
) | ||
|
||
type SPDXConverter struct { | ||
// the root directory to begin replacing | ||
// license clauses to spdx clauses | ||
rootDir string | ||
} | ||
|
||
// Walk will begin walking the tree rooted at | ||
// rootDir. | ||
// | ||
// For each .go file it encounters it will parse | ||
// that file's AST and discover the comments. | ||
// | ||
// If the comments indicate a non spdx license | ||
// it will convert it to one and write the file back | ||
// to disk. | ||
func (s *SPDXConverter) Walk() error { | ||
err := filepath.WalkDir(s.rootDir, func(path string, d os.DirEntry, e error) error { | ||
if e != nil { | ||
return e | ||
} | ||
if filepath.Ext(path) != ".go" { | ||
return nil | ||
} | ||
fs := token.NewFileSet() | ||
astFd, err := parser.ParseFile(fs, path, nil, parser.ParseComments) | ||
if err != nil { | ||
return fmt.Errorf("error while parsing %v: %w", path, err) | ||
} | ||
|
||
err = s.conv(path, fs, astFd) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
}) | ||
return err | ||
} | ||
|
||
func (s *SPDXConverter) conv(path string, fset *token.FileSet, f *ast.File) error { | ||
if len(f.Comments) == 0 { | ||
return nil | ||
} | ||
cg := f.Comments[0] | ||
if !strings.HasPrefix(cg.List[0].Text, "// Copyright") { | ||
log.Printf("file %v did not start with a Copyright string. skipping...", path) | ||
return nil | ||
} | ||
var spdx string | ||
for exp, tmp := range RegexpMap { | ||
if exp.MatchString(cg.Text()) { | ||
spdx = tmp | ||
} | ||
} | ||
if spdx == "" { | ||
log.Printf("could not determine license for %v", path) | ||
return nil | ||
} | ||
|
||
copyRight := cg.List[0].Text | ||
cg.List[0].Text, cg.List[1].Text = spdx, copyRight | ||
cg.List = cg.List[:2] | ||
|
||
fd, err := os.OpenFile(path, os.O_TRUNC|os.O_RDWR, 0660) | ||
if err != nil { | ||
return fmt.Errorf("failed to open original source file for conversion: %w", err) | ||
} | ||
defer fd.Close() | ||
|
||
err = format.Node(fd, fset, f) | ||
if err != nil { | ||
return fmt.Errorf("failed to write converted file %v: %w", path, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func main() { | ||
switch { | ||
case len(os.Args) != 2: | ||
fmt.Print(usage) | ||
os.Exit(1) | ||
case os.Args[1] == "help": | ||
fmt.Print(usage) | ||
os.Exit(0) | ||
} | ||
|
||
path := os.Args[1] | ||
dir, err := os.Stat(path) | ||
if err != nil { | ||
fmt.Printf("provided path %v could not be opened: %v", path, err) | ||
os.Exit(1) | ||
} | ||
if !dir.IsDir() { | ||
fmt.Println("provided path is not a directory") | ||
os.Exit(1) | ||
} | ||
|
||
conv := &SPDXConverter{ | ||
rootDir: path, | ||
} | ||
if err := conv.Walk(); err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
} |