Skip to content

Commit

Permalink
Works around missing Module.dir for vendored Modules
Browse files Browse the repository at this point in the history
  • Loading branch information
jaxesn committed Jan 4, 2023
1 parent 92428a6 commit b336f76
Showing 1 changed file with 51 additions and 34 deletions.
85 changes: 51 additions & 34 deletions licenses/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"fmt"
"go/build"
"path"
"path/filepath"
"sort"
"strings"
Expand Down Expand Up @@ -117,7 +118,14 @@ func Libraries(ctx context.Context, classifier Classifier, includeTests bool, ig
klog.Errorf("Package %s does not have module info. Non go modules projects are no longer supported. For feedback, refer to https://github.com/google/go-licenses/issues/128.", p.PkgPath)
return false
}
licensePath, err := Find(pkgDir, p.Module.Dir, classifier)

stopAt := p.Module.Dir
if isVendorModule(newModule(p.Module), pkgDir) {
splits := strings.SplitN(pkgDir, "/vendor/", 2)
stopAt = path.Join(splits[0], "vendor", p.Module.Path)
}

licensePath, err := Find(pkgDir, stopAt, classifier)
if err != nil {
klog.Errorf("Failed to find license for %s: %v", p.PkgPath, err)
}
Expand Down Expand Up @@ -156,43 +164,25 @@ func Libraries(ctx context.Context, classifier Classifier, includeTests bool, ig
lib.module = newModule(pkg.Module)
}
}
if lib.module != nil && lib.module.Path != "" && lib.module.Dir == "" {
// A known cause is that the module is vendored, so some information is lost.
if isVendorModule(lib.module, lib.LicensePath) {
splits := strings.SplitN(lib.LicensePath, "/vendor/", 2)
if len(splits) != 2 {
klog.Warningf("module %s does not have dir and it's not vendored, cannot discover the license URL. Report to go-licenses developer if you see this.", lib.module.Path)
} else {
// This is vendored. Handle this known special case.

// Extra note why we identify a vendored package like this.
//
// For a normal package:
// * if it's not in a module, lib.module == nil
// * if it's in a module, lib.module.Dir != ""
// Only vendored modules will have lib.module != nil && lib.module.Path != "" && lib.module.Dir == "" as far as I know.
// So the if condition above is already very strict for vendored packages.
// On top of it, we checked the lib.LicensePath contains a vendor folder in it.
// So it's rare to have a false positive for both conditions at the same time, although it may happen in theory.
//
// These assumptions may change in the future,
// so we need to keep this updated with go tooling changes.
parentModDir := splits[0]
var parentPkg *packages.Package
for _, rootPkg := range rootPkgs {
if rootPkg.Module != nil && rootPkg.Module.Dir == parentModDir {
parentPkg = rootPkg
break
}
}
if parentPkg == nil {
klog.Warningf("cannot find parent package of vendored module %s", lib.module.Path)
} else {
// Vendored modules should be commited in the parent module, so it counts as part of the
// parent module.
lib.module = newModule(parentPkg.Module)
parentModDir := splits[0]
var parentPkg *packages.Package
for _, rootPkg := range rootPkgs {
if rootPkg.Module != nil && rootPkg.Module.Dir == parentModDir {
parentPkg = rootPkg
break
}
}
if parentPkg == nil {
klog.Warningf("cannot find parent package of vendored module %s", lib.module.Path)
} else {
// Vendored modules should be commited in the parent module, so it counts as part of the
// parent module.
lib.module = newModule(parentPkg.Module)
}
}

libraries = append(libraries, lib)
}
// Sort libraries to produce a stable result for snapshot diffing.
Expand Down Expand Up @@ -228,6 +218,33 @@ func commonAncestor(paths []string) string {
return min
}

func isVendorModule(module *Module, path string) bool {
if module != nil && module.Path != "" && module.Dir == "" {
// A known cause is that the module is vendored, so some information is lost.
splits := strings.SplitN(path, "/vendor/", 2)
if len(splits) != 2 {
klog.Warningf("module %s does not have dir and it's not vendored, cannot discover the license URL. Report to go-licenses developer if you see this.", module.Path)
} else {
// This is vendored. Handle this known special case.

// Extra note why we identify a vendored package like this.
//
// For a normal package:
// * if it's not in a module, lib.module == nil
// * if it's in a module, lib.module.Dir != ""
// Only vendored modules will have lib.module != nil && lib.module.Path != "" && lib.module.Dir == "" as far as I know.
// So the if condition above is already very strict for vendored packages.
// On top of it, we checked the lib.LicensePath contains a vendor folder in it.
// So it's rare to have a false positive for both conditions at the same time, although it may happen in theory.
//
// These assumptions may change in the future,
// so we need to keep this updated with go tooling changes.
return true
}
}
return false
}

func (l *Library) String() string {
return l.Name()
}
Expand Down

0 comments on commit b336f76

Please sign in to comment.