Skip to content

Commit

Permalink
feat(v2/csv): use module dir as find license boundary
Browse files Browse the repository at this point in the history
  • Loading branch information
Bobgy committed Jan 5, 2022
1 parent d5b7edc commit e06b387
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 82 deletions.
40 changes: 5 additions & 35 deletions v2/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"context"
"encoding/csv"
"os"
"strings"

"github.com/golang/glog"
"github.com/google/go-licenses/v2/licenses"
Expand Down Expand Up @@ -56,41 +55,12 @@ func csvMain(_ *cobra.Command, args []string) error {
}
for _, lib := range libs {
licenseURL := "Unknown"
licenseName := "Unknown"
if lib.LicensePath != "" {
// Find a URL for the license file, based on the URL of a remote for the Git repository.
var errs []string
repo, err := licenses.FindGitRepo(lib.LicensePath)
if err != nil {
// Can't find Git repo (possibly a Go Module?) - derive URL from lib name instead.
lURL, err := lib.FileURL(lib.LicensePath)
if err != nil {
errs = append(errs, err.Error())
} else {
licenseURL = lURL.String()
}
} else {
for _, remote := range gitRemotes {
url, err := repo.FileURL(lib.LicensePath, remote)
if err != nil {
errs = append(errs, err.Error())
continue
}
licenseURL = url.String()
break
}
}
if licenseURL == "Unknown" {
glog.Errorf("Error discovering URL for %q:\n- %s", lib.LicensePath, strings.Join(errs, "\n- "))
}
licenseName, _, err = classifier.Identify(lib.LicensePath)
if err != nil {
glog.Errorf("Error identifying license in %q: %v", lib.LicensePath, err)
licenseName = "Unknown"
}
licenseName, _, err := classifier.Identify(lib.LicensePath)
if err != nil {
glog.Errorf("Error identifying license in %q: %v", lib.LicensePath, err)
licenseName = "Unknown"
}
// Remove the "*/vendor/" prefix from the library name for conciseness.
if err := writer.Write([]string{unvendor(lib.Name()), licenseURL, licenseName}); err != nil {
if err := writer.Write([]string{lib.Name(), licenseURL, licenseName}); err != nil {
return err
}
}
Expand Down
47 changes: 21 additions & 26 deletions v2/licenses/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,34 @@ package licenses

import (
"fmt"
"go/build"
"io/ioutil"
"path/filepath"
"regexp"
"strings"
)

var (
licenseRegexp = regexp.MustCompile(`^(?i)(LICEN(S|C)E|COPYING|README|NOTICE).*$`)
srcDirRegexps = func() []*regexp.Regexp {
var rs []*regexp.Regexp
for _, s := range build.Default.SrcDirs() {
rs = append(rs, regexp.MustCompile("^"+regexp.QuoteMeta(s)+"$"))
}
return rs
}()
vendorRegexp = regexp.MustCompile(`.+/vendor(/)?$`)
)

// Find returns the file path of the license for this package.
func Find(dir string, classifier Classifier) (string, error) {
var stopAt []*regexp.Regexp
stopAt = append(stopAt, srcDirRegexps...)
stopAt = append(stopAt, vendorRegexp)
return findUpwards(dir, licenseRegexp, stopAt, func(path string) bool {
//
// dir is path of the directory where we want to find a license.
// rootDir is path of the module containing this package. Find will not search out of the
// rootDir.
func Find(dir string, rootDir string, classifier Classifier) (string, error) {
dir, err := filepath.Abs(dir)
if err != nil {
return "", err
}
rootDir, err = filepath.Abs(rootDir)
if err != nil {
return "", err
}
if !strings.HasPrefix(dir, rootDir) {
return "", fmt.Errorf("licenses.Find: rootDir %s should contain dir %s", rootDir, dir)
}
return findUpwards(dir, licenseRegexp, rootDir, func(path string) bool {
// TODO(RJPercival): Return license details
if _, _, err := classifier.Identify(path); err != nil {
return false
Expand All @@ -48,15 +52,15 @@ func Find(dir string, classifier Classifier) (string, error) {
})
}

func findUpwards(dir string, r *regexp.Regexp, stopAt []*regexp.Regexp, predicate func(path string) bool) (string, error) {
func findUpwards(dir string, r *regexp.Regexp, stopAt string, predicate func(path string) bool) (string, error) {
// Dir must be made absolute for reliable matching with stopAt regexps
dir, err := filepath.Abs(dir)
if err != nil {
return "", err
}
start := dir
// Stop once dir matches a stopAt regexp or dir is the filesystem root
for !matchAny(stopAt, dir) {
// Stop once we go out of the stopAt dir.
for strings.HasPrefix(dir, stopAt) {
dirContents, err := ioutil.ReadDir(dir)
if err != nil {
return "", err
Expand All @@ -79,12 +83,3 @@ func findUpwards(dir string, r *regexp.Regexp, stopAt []*regexp.Regexp, predicat
}
return "", fmt.Errorf("no file/directory matching regexp %q found for %s", r, start)
}

func matchAny(patterns []*regexp.Regexp, s string) bool {
for _, p := range patterns {
if p.MatchString(s) {
return true
}
}
return false
}
11 changes: 6 additions & 5 deletions v2/licenses/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ type GitRepo struct {
// FindGitRepo finds the Git repository that contains the specified filePath
// by searching upwards through the directory tree for a ".git" directory.
func FindGitRepo(filePath string) (*GitRepo, error) {
path, err := findUpwards(filepath.Dir(filePath), gitRegexp, srcDirRegexps, nil)
if err != nil {
return nil, err
}
return &GitRepo{dotGitPath: path}, nil
return nil, nil
// path, err := findUpwards(filepath.Dir(filePath), gitRegexp, srcDirRegexps, nil)
// if err != nil {
// return nil, err
// }
// return &GitRepo{dotGitPath: path}, nil
}

// FileURL returns the URL of a file stored in a Git repository.
Expand Down
8 changes: 6 additions & 2 deletions v2/licenses/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (e PackagesError) Error() string {
func Libraries(ctx context.Context, classifier Classifier, importPaths ...string) ([]*Library, error) {
cfg := &packages.Config{
Context: ctx,
Mode: packages.NeedImports | packages.NeedDeps | packages.NeedFiles | packages.NeedName,
Mode: packages.NeedImports | packages.NeedDeps | packages.NeedFiles | packages.NeedName | packages.NeedModule,
}

rootPkgs, err := packages.Load(cfg, importPaths...)
Expand Down Expand Up @@ -103,7 +103,7 @@ func Libraries(ctx context.Context, classifier Classifier, importPaths ...string
// This package is empty - nothing to do.
return true
}
licensePath, err := Find(pkgDir, classifier)
licensePath, err := Find(pkgDir, p.Module.Dir, classifier)
if err != nil {
glog.Errorf("Failed to find license for %s: %v", p.PkgPath, err)
}
Expand Down Expand Up @@ -202,6 +202,10 @@ func (l *Library) FileURL(filePath string) (*url.URL, error) {

// isStdLib returns true if this package is part of the Go standard library.
func isStdLib(pkg *packages.Package) bool {
if pkg.Name == "unsafe" {
// Special case unsafe stdlib, because it does not contain go files.
return true
}
if len(pkg.GoFiles) == 0 {
return false
}
Expand Down
29 changes: 15 additions & 14 deletions v2/third_party/licenses.csv
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
github.com/emirpasic/gods,https://github.com/emirpasic/gods/blob/master/LICENSE,BSD-2-Clause
github.com/golang/glog,https://github.com/golang/glog/blob/master/LICENSE,Apache-2.0
github.com/google/go-licenses/v2,Unknown,Apache-2.0
github.com/google/licenseclassifier,https://github.com/google/licenseclassifier/blob/master/LICENSE,Apache-2.0
github.com/google/licenseclassifier/stringclassifier,https://github.com/google/licenseclassifier/blob/master/stringclassifier/LICENSE,Apache-2.0
github.com/jbenet/go-context/io,https://github.com/jbenet/go-context/blob/master/io/LICENSE,MIT
github.com/kevinburke/ssh_config,https://github.com/kevinburke/ssh_config/blob/master/LICENSE,MIT
github.com/mitchellh/go-homedir,https://github.com/mitchellh/go-homedir/blob/master/LICENSE,MIT
github.com/otiai10/copy,https://github.com/otiai10/copy/blob/master/LICENSE,MIT
github.com/sergi/go-diff/diffmatchpatch,https://github.com/sergi/go-diff/blob/master/diffmatchpatch/LICENSE,MIT
github.com/spf13/cobra,https://github.com/spf13/cobra/blob/master/LICENSE.txt,Apache-2.0
github.com/spf13/pflag,https://github.com/spf13/pflag/blob/master/LICENSE,BSD-3-Clause
github.com/src-d/gcfg,https://github.com/src-d/gcfg/blob/master/LICENSE,BSD-3-Clause
github.com/xanzy/ssh-agent,https://github.com/xanzy/ssh-agent/blob/master/LICENSE,Apache-2.0
github.com/emirpasic/gods,Unknown,BSD-2-Clause
github.com/golang/glog,Unknown,Apache-2.0
github.com/google/go-licenses/v2,Unknown,
github.com/google/go-licenses/v2/licenses,Unknown,
github.com/google/licenseclassifier,Unknown,Apache-2.0
github.com/google/licenseclassifier/stringclassifier,Unknown,Apache-2.0
github.com/jbenet/go-context/io,Unknown,MIT
github.com/kevinburke/ssh_config,Unknown,MIT
github.com/mitchellh/go-homedir,Unknown,MIT
github.com/otiai10/copy,Unknown,MIT
github.com/sergi/go-diff/diffmatchpatch,Unknown,MIT
github.com/spf13/cobra,Unknown,Apache-2.0
github.com/spf13/pflag,Unknown,BSD-3-Clause
github.com/src-d/gcfg,Unknown,BSD-3-Clause
github.com/xanzy/ssh-agent,Unknown,Apache-2.0
golang.org/x/crypto,Unknown,BSD-3-Clause
golang.org/x/mod/semver,Unknown,BSD-3-Clause
golang.org/x/net,Unknown,BSD-3-Clause
Expand Down

0 comments on commit e06b387

Please sign in to comment.