aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/ryancurrah
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-09-15 18:05:35 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-09-15 19:34:30 +0200
commit712de1c63d9db97c81af68cd0dc4372c53d2e57a (patch)
treeae1761fec52c3ae4ddd003a4130ddbda8d0a2d69 /vendor/github.com/ryancurrah
parent298a69c38dd5c8a9bbd7a022e88f4ddbcf885e16 (diff)
vendor/github.com/golangci/golangci-lint: update to v1.31
Diffstat (limited to 'vendor/github.com/ryancurrah')
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/.gitignore2
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/.golangci.yml6
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml13
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/Makefile16
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/README.md21
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/cmd.go239
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/go.mod2
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/go.sum4
-rw-r--r--vendor/github.com/ryancurrah/gomodguard/gomodguard.go371
9 files changed, 525 insertions, 149 deletions
diff --git a/vendor/github.com/ryancurrah/gomodguard/.gitignore b/vendor/github.com/ryancurrah/gomodguard/.gitignore
index 5131b46d6..030056d46 100644
--- a/vendor/github.com/ryancurrah/gomodguard/.gitignore
+++ b/vendor/github.com/ryancurrah/gomodguard/.gitignore
@@ -19,3 +19,5 @@
*.xml
dist/
+
+coverage.* \ No newline at end of file
diff --git a/vendor/github.com/ryancurrah/gomodguard/.golangci.yml b/vendor/github.com/ryancurrah/gomodguard/.golangci.yml
new file mode 100644
index 000000000..9c19e63a1
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/.golangci.yml
@@ -0,0 +1,6 @@
+linters:
+ enable-all: true
+ disable:
+ - funlen
+ - gochecknoglobals
+ - lll
diff --git a/vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml b/vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml
index c0f061f59..38a2f0be0 100644
--- a/vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml
+++ b/vendor/github.com/ryancurrah/gomodguard/.gomodguard.yaml
@@ -2,7 +2,7 @@ allowed:
modules: # List of allowed modules
- gopkg.in/yaml.v2
- github.com/go-xmlfmt/xmlfmt
- - github.com/phayes/checkstyle
+ - github.com/Masterminds/semver
domains: # List of allowed module domains
- golang.org
@@ -15,4 +15,13 @@ blocked:
- github.com/mitchellh/go-homedir:
recommendations:
- github.com/ryancurrah/gomodguard
- reason: "testing if the linted module is not blocked when it is recommended"
+ reason: "testing if the current/linted module is not blocked when it is recommended"
+ - github.com/phayes/checkstyle:
+ recommendations:
+ - github.com/someother/module
+ reason: "testing if module is blocked with recommendation"
+
+ versions:
+ - github.com/mitchellh/go-homedir:
+ version: "<= 1.1.0"
+ reason: "testing if blocked version constraint works."
diff --git a/vendor/github.com/ryancurrah/gomodguard/Makefile b/vendor/github.com/ryancurrah/gomodguard/Makefile
index d765f52d5..9af2f76e4 100644
--- a/vendor/github.com/ryancurrah/gomodguard/Makefile
+++ b/vendor/github.com/ryancurrah/gomodguard/Makefile
@@ -3,7 +3,7 @@ version = $(shell printf '%s' $$(cat VERSION))
.PHONEY: lint
lint:
- golangci-lint run -v --enable-all --disable funlen,gochecknoglobals,lll ./...
+ golangci-lint run ./...
.PHONEY: build
build:
@@ -17,6 +17,14 @@ dockerbuild:
run: build
./gomodguard
+.PHONEY: test
+test:
+ go test -v -coverprofile coverage.out
+
+.PHONEY: cover
+cover:
+ gocover-cobertura < coverage.out > coverage.xml
+
.PHONEY: dockerrun
dockerrun: dockerbuild
docker run -v "${current_dir}/.gomodguard.yaml:/.gomodguard.yaml" ryancurrah/gomodguard:latest
@@ -30,8 +38,12 @@ release:
.PHONEY: clean
clean:
rm -rf dist/
- rm -f gomodguard
+ rm -f gomodguard coverage.xml coverage.out
.PHONEY: install-tools-mac
install-tools-mac:
brew install goreleaser/tap/goreleaser
+
+.PHONEY: install-go-tools
+install-go-tools:
+ go get github.com/t-yuki/gocover-cobertura
diff --git a/vendor/github.com/ryancurrah/gomodguard/README.md b/vendor/github.com/ryancurrah/gomodguard/README.md
index 89a2398be..f09b5e1f4 100644
--- a/vendor/github.com/ryancurrah/gomodguard/README.md
+++ b/vendor/github.com/ryancurrah/gomodguard/README.md
@@ -1,4 +1,6 @@
# gomodguard
+![Codecov](https://img.shields.io/codecov/c/gh/ryancurrah/gomodguard?style=flat-square)
+![GitHub Workflow Status](https://img.shields.io/github/workflow/status/ryancurrah/gomodguard/Go?logo=Go&style=flat-square)
<img src="https://storage.googleapis.com/gopherizeme.appspot.com/gophers/9afcc208898c763be95f046eb2f6080146607209.png" width="30%">
@@ -18,6 +20,8 @@ Alternative modules can be optionally recommended in the blocked modules list.
If the linted module imports a blocked module but the linted module is in the recommended modules list the blocked module is ignored. Usually, this means the linted module wraps that blocked module for use by other modules, therefore the import of the blocked module should not be blocked.
+Version constraints can be specified for modules as well which lets you block new or old versions of modules or specific versions.
+
Results are printed to `stdout`.
Logging statements are printed to `stderr`.
@@ -42,6 +46,10 @@ blocked:
recommendations: # Recommended modules that should be used instead (Optional)
- golang.org/x/mod
reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
+ versions: # List of blocked module version constraints.
+ - github.com/mitchellh/go-homedir: # Blocked module with version constraint.
+ version: "<= 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons.
+ reason: "testing if blocked version constraint works." # Reason why the version constraint exists.
```
## Usage
@@ -52,17 +60,22 @@ Usage: gomodguard <file> [files...]
Also supports package syntax but will use it in relative path, i.e. ./pkg/...
Flags:
-f string
- Report results to the specified file. A report type must also be specified
+ Report results to the specified file. A report type must also be specified
-file string
- -h Show this help text
+ -h Show this help text
-help
- -n Don't lint test files
+ -i int
+ Exit code when issues were found (default 2)
+ -issues-exit-code int
+ (default 2)
+
+ -n Don't lint test files
-no-test
-r string
- Report results to one of the following formats: checkstyle. A report file destination must also be specified
+ Report results to one of the following formats: checkstyle. A report file destination must also be specified
-report string
```
diff --git a/vendor/github.com/ryancurrah/gomodguard/cmd.go b/vendor/github.com/ryancurrah/gomodguard/cmd.go
new file mode 100644
index 000000000..652e61f8c
--- /dev/null
+++ b/vendor/github.com/ryancurrah/gomodguard/cmd.go
@@ -0,0 +1,239 @@
+package gomodguard
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/go-xmlfmt/xmlfmt"
+ "github.com/mitchellh/go-homedir"
+ "github.com/phayes/checkstyle"
+ "gopkg.in/yaml.v2"
+)
+
+const (
+ errFindingHomedir = "unable to find home directory, %w"
+ errReadingConfigFile = "could not read config file: %w"
+ errParsingConfigFile = "could not parse config file: %w"
+)
+
+var (
+ configFile = ".gomodguard.yaml"
+ logger = log.New(os.Stderr, "", 0)
+ errFindingConfigFile = fmt.Errorf("could not find config file")
+)
+
+// Run the gomodguard linter. Returns the exit code to use.
+func Run() int {
+ var (
+ args []string
+ help bool
+ noTest bool
+ report string
+ reportFile string
+ issuesExitCode int
+ cwd, _ = os.Getwd()
+ )
+
+ flag.BoolVar(&help, "h", false, "Show this help text")
+ flag.BoolVar(&help, "help", false, "")
+ flag.BoolVar(&noTest, "n", false, "Don't lint test files")
+ flag.BoolVar(&noTest, "no-test", false, "")
+ flag.StringVar(&report, "r", "", "Report results to one of the following formats: checkstyle. A report file destination must also be specified")
+ flag.StringVar(&report, "report", "", "")
+ flag.StringVar(&reportFile, "f", "", "Report results to the specified file. A report type must also be specified")
+ flag.StringVar(&reportFile, "file", "", "")
+ flag.IntVar(&issuesExitCode, "i", 2, "Exit code when issues were found")
+ flag.IntVar(&issuesExitCode, "issues-exit-code", 2, "")
+ flag.Parse()
+
+ report = strings.TrimSpace(strings.ToLower(report))
+
+ if help {
+ showHelp()
+ return 0
+ }
+
+ if report != "" && report != "checkstyle" {
+ logger.Fatalf("error: invalid report type '%s'", report)
+ }
+
+ if report != "" && reportFile == "" {
+ logger.Fatalf("error: a report file must be specified when a report is enabled")
+ }
+
+ if report == "" && reportFile != "" {
+ logger.Fatalf("error: a report type must be specified when a report file is enabled")
+ }
+
+ args = flag.Args()
+ if len(args) == 0 {
+ args = []string{"./..."}
+ }
+
+ config, err := GetConfig(configFile)
+ if err != nil {
+ logger.Fatalf("error: %s", err)
+ }
+
+ filteredFiles := GetFilteredFiles(cwd, noTest, args)
+
+ processor, err := NewProcessor(*config, logger)
+ if err != nil {
+ logger.Fatalf("error: %s", err)
+ }
+
+ results := processor.ProcessFiles(filteredFiles)
+
+ if report == "checkstyle" {
+ err := WriteCheckstyle(reportFile, results)
+ if err != nil {
+ logger.Fatalf("error: %s", err)
+ }
+ }
+
+ for _, r := range results {
+ fmt.Println(r.String())
+ }
+
+ if len(results) > 0 {
+ return issuesExitCode
+ }
+
+ return 0
+}
+
+// GetConfig from YAML file.
+func GetConfig(configFile string) (*Configuration, error) {
+ config := Configuration{}
+
+ home, err := homedir.Dir()
+ if err != nil {
+ return nil, fmt.Errorf(errFindingHomedir, err)
+ }
+
+ cfgFile := ""
+ homeDirCfgFile := filepath.Join(home, configFile)
+
+ switch {
+ case fileExists(configFile):
+ cfgFile = configFile
+ case fileExists(homeDirCfgFile):
+ cfgFile = homeDirCfgFile
+ default:
+ return nil, fmt.Errorf("%w: %s %s", errFindingConfigFile, configFile, homeDirCfgFile)
+ }
+
+ data, err := ioutil.ReadFile(cfgFile)
+ if err != nil {
+ return nil, fmt.Errorf(errReadingConfigFile, err)
+ }
+
+ err = yaml.Unmarshal(data, &config)
+ if err != nil {
+ return nil, fmt.Errorf(errParsingConfigFile, err)
+ }
+
+ return &config, nil
+}
+
+// GetFilteredFiles returns files based on search string arguments and filters.
+func GetFilteredFiles(cwd string, skipTests bool, args []string) []string {
+ var (
+ foundFiles = []string{}
+ filteredFiles = []string{}
+ )
+
+ for _, f := range args {
+ if strings.HasSuffix(f, "/...") {
+ dir, _ := filepath.Split(f)
+
+ foundFiles = append(foundFiles, expandGoWildcard(dir)...)
+
+ continue
+ }
+
+ if _, err := os.Stat(f); err == nil {
+ foundFiles = append(foundFiles, f)
+ }
+ }
+
+ // Use relative path to print shorter names, sort out test foundFiles if chosen.
+ for _, f := range foundFiles {
+ if skipTests {
+ if strings.HasSuffix(f, "_test.go") {
+ continue
+ }
+ }
+
+ if relativePath, err := filepath.Rel(cwd, f); err == nil {
+ filteredFiles = append(filteredFiles, relativePath)
+
+ continue
+ }
+
+ filteredFiles = append(filteredFiles, f)
+ }
+
+ return filteredFiles
+}
+
+// showHelp text for command line.
+func showHelp() {
+ helpText := `Usage: gomodguard <file> [files...]
+Also supports package syntax but will use it in relative path, i.e. ./pkg/...
+Flags:`
+ fmt.Println(helpText)
+ flag.PrintDefaults()
+}
+
+// WriteCheckstyle takes the results and writes them to a checkstyle formated file.
+func WriteCheckstyle(checkstyleFilePath string, results []Result) error {
+ check := checkstyle.New()
+
+ for i := range results {
+ file := check.EnsureFile(results[i].FileName)
+ file.AddError(checkstyle.NewError(results[i].LineNumber, 1, checkstyle.SeverityError, results[i].Reason, "gomodguard"))
+ }
+
+ checkstyleXML := fmt.Sprintf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n%s", check.String())
+
+ err := ioutil.WriteFile(checkstyleFilePath, []byte(xmlfmt.FormatXML(checkstyleXML, "", " ")), 0644) // nolint:gosec
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// fileExists returns true if the file path provided exists.
+func fileExists(filename string) bool {
+ info, err := os.Stat(filename)
+ if os.IsNotExist(err) {
+ return false
+ }
+
+ return !info.IsDir()
+}
+
+// expandGoWildcard path provided.
+func expandGoWildcard(root string) []string {
+ foundFiles := []string{}
+
+ _ = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
+ // Only append go foundFiles.
+ if !strings.HasSuffix(info.Name(), ".go") {
+ return nil
+ }
+
+ foundFiles = append(foundFiles, path)
+
+ return nil
+ })
+
+ return foundFiles
+}
diff --git a/vendor/github.com/ryancurrah/gomodguard/go.mod b/vendor/github.com/ryancurrah/gomodguard/go.mod
index 0f0e92e4e..15231c986 100644
--- a/vendor/github.com/ryancurrah/gomodguard/go.mod
+++ b/vendor/github.com/ryancurrah/gomodguard/go.mod
@@ -3,9 +3,11 @@ module github.com/ryancurrah/gomodguard
go 1.14
require (
+ github.com/Masterminds/semver v1.5.0
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b
github.com/mitchellh/go-homedir v1.1.0
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d
+ github.com/pkg/errors v0.9.1
golang.org/x/mod v0.2.0
gopkg.in/yaml.v2 v2.2.8
)
diff --git a/vendor/github.com/ryancurrah/gomodguard/go.sum b/vendor/github.com/ryancurrah/gomodguard/go.sum
index 0f4bf3231..55ae4e571 100644
--- a/vendor/github.com/ryancurrah/gomodguard/go.sum
+++ b/vendor/github.com/ryancurrah/gomodguard/go.sum
@@ -1,9 +1,13 @@
+github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
+github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo=
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA=
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
diff --git a/vendor/github.com/ryancurrah/gomodguard/gomodguard.go b/vendor/github.com/ryancurrah/gomodguard/gomodguard.go
index cd4f7d66e..16467734c 100644
--- a/vendor/github.com/ryancurrah/gomodguard/gomodguard.go
+++ b/vendor/github.com/ryancurrah/gomodguard/gomodguard.go
@@ -12,25 +12,104 @@ import (
"os/exec"
"strings"
+ "github.com/Masterminds/semver"
+
"golang.org/x/mod/modfile"
)
+const (
+ goModFilename = "go.mod"
+ errReadingGoModFile = "unable to read go mod file %s: %w"
+ errParsingGoModFile = "unable to parsing go mod file %s: %w"
+)
+
var (
- blockedReasonNotInAllowedList = "import of package `%s` is blocked because the module is not in the allowed modules list."
- blockedReasonInBlockedList = "import of package `%s` is blocked because the module is in the blocked modules list."
- goModFilename = "go.mod"
+ blockReasonNotInAllowedList = "import of package `%s` is blocked because the module is not in the allowed modules list."
+ blockReasonInBlockedList = "import of package `%s` is blocked because the module is in the blocked modules list."
)
-// Recommendations are alternative modules to use and a reason why.
-type Recommendations struct {
- Recommendations []string `yaml:"recommendations"`
- Reason string `yaml:"reason"`
+// BlockedVersion has a version constraint a reason why the the module version is blocked.
+type BlockedVersion struct {
+ Version string `yaml:"version"`
+ Reason string `yaml:"reason"`
+ lintedModuleVersion string `yaml:"-"`
+}
+
+// Set required values for performing checks. This must be ran before running anything else.
+func (r *BlockedVersion) Set(lintedModuleVersion string) {
+ r.lintedModuleVersion = lintedModuleVersion
+}
+
+// IsAllowed returns true if the blocked module is allowed. You must Set() values first.
+func (r *BlockedVersion) IsAllowed() bool {
+ return !r.isLintedModuleVersionBlocked()
+}
+
+// isLintedModuleVersionBlocked returns true if version constraint specified and the
+// linted module version meets the constraint.
+func (r *BlockedVersion) isLintedModuleVersionBlocked() bool {
+ if r.Version == "" {
+ return false
+ }
+
+ constraint, err := semver.NewConstraint(r.Version)
+ if err != nil {
+ return false
+ }
+
+ version, err := semver.NewVersion(strings.TrimLeft(r.lintedModuleVersion, "v"))
+ if err != nil {
+ return false
+ }
+
+ return constraint.Check(version)
+}
+
+// Message returns the reason why the module version is blocked.
+func (r *BlockedVersion) Message() string {
+ msg := ""
+
+ // Add version contraint to message
+ msg += fmt.Sprintf("version `%s` is blocked because it does not meet the version constraint `%s`.", r.lintedModuleVersion, r.Version)
+
+ if r.Reason == "" {
+ return msg
+ }
+
+ // Add reason to message
+ msg += fmt.Sprintf(" %s.", strings.TrimRight(r.Reason, "."))
+
+ return msg
+}
+
+// BlockedModule has alternative modules to use and a reason why the module is blocked.
+type BlockedModule struct {
+ Recommendations []string `yaml:"recommendations"`
+ Reason string `yaml:"reason"`
+ currentModuleName string `yaml:"-"`
}
-// IsRecommended returns true if the package provided is in the Recommendations list
-func (r *Recommendations) IsRecommended(pkg string) bool {
+// Set required values for performing checks. This must be ran before running anything else.
+func (r *BlockedModule) Set(currentModuleName string) {
+ r.currentModuleName = currentModuleName
+}
+
+// IsAllowed returns true if the blocked module is allowed. You must Set() values first.
+func (r *BlockedModule) IsAllowed() bool {
+ // If the current go.mod file being linted is a recommended module of a
+ // blocked module and it imports that blocked module, do not set as blocked.
+ // This could mean that the linted module is a wrapper for that blocked module.
+ return r.isCurrentModuleARecommendation()
+}
+
+// isCurrentModuleARecommendation returns true if the current module is in the Recommendations list.
+func (r *BlockedModule) isCurrentModuleARecommendation() bool {
+ if r == nil {
+ return false
+ }
+
for n := range r.Recommendations {
- if strings.TrimSpace(pkg) == strings.TrimSpace(r.Recommendations[n]) {
+ if strings.TrimSpace(r.currentModuleName) == strings.TrimSpace(r.Recommendations[n]) {
return true
}
}
@@ -38,14 +117,11 @@ func (r *Recommendations) IsRecommended(pkg string) bool {
return false
}
-// String returns the recommended modules and reason message.
-func (r *Recommendations) String() string {
+// Message returns the reason why the module is blocked and a list of recommended modules if provided.
+func (r *BlockedModule) Message() string {
msg := ""
- if r == nil {
- return msg
- }
-
+ // Add recommendations to message
for i := range r.Recommendations {
switch {
case len(r.Recommendations) == 1:
@@ -59,8 +135,15 @@ func (r *Recommendations) String() string {
}
}
- if r.Reason != "" {
- msg += fmt.Sprintf(" %s", r.Reason)
+ if r.Reason == "" {
+ return msg
+ }
+
+ // Add reason to message
+ if msg == "" {
+ msg = fmt.Sprintf("%s.", strings.TrimRight(r.Reason, "."))
+ } else {
+ msg += fmt.Sprintf(" %s.", strings.TrimRight(r.Reason, "."))
}
return msg
@@ -68,25 +151,24 @@ func (r *Recommendations) String() string {
// HasRecommendations returns true if the blocked package has
// recommended modules.
-func (r *Recommendations) HasRecommendations() bool {
+func (r *BlockedModule) HasRecommendations() bool {
+ if r == nil {
+ return false
+ }
+
return len(r.Recommendations) > 0
}
-// BlockedModule is a blocked module name and
-// optionally a list of recommended modules
-// and a reason message.
-type BlockedModule map[string]Recommendations
+// BlockedVersions a list of blocked modules by a version constraint.
+type BlockedVersions []map[string]BlockedVersion
-// BlockedModules a list of blocked modules.
-type BlockedModules []BlockedModule
-
-// Get returns the modules that are blocked.
-func (b BlockedModules) Get() []string {
+// Get returns the module names that are blocked.
+func (b BlockedVersions) Get() []string {
modules := make([]string, len(b))
- for i := range b {
- for module := range b[i] {
- modules[i] = module
+ for n := range b {
+ for module := range b[n] {
+ modules[n] = module
break
}
}
@@ -94,46 +176,49 @@ func (b BlockedModules) Get() []string {
return modules
}
-// RecommendedModules will return a list of recommended modules for the
-// package provided. If there is no recommendation nil will be returned.
-func (b BlockedModules) RecommendedModules(pkg string) *Recommendations {
- for i := range b {
- for blockedModule, recommendations := range b[i] {
- if strings.HasPrefix(strings.ToLower(pkg), strings.ToLower(blockedModule)) && recommendations.HasRecommendations() {
- return &recommendations
+// GetBlockReason returns a block version if one is set for the provided linted module name.
+func (b BlockedVersions) GetBlockReason(lintedModuleName, lintedModuleVersion string) *BlockedVersion {
+ for _, blockedModule := range b {
+ for blockedModuleName, blockedVersion := range blockedModule {
+ if strings.EqualFold(strings.TrimSpace(lintedModuleName), strings.TrimSpace(blockedModuleName)) {
+ blockedVersion.Set(lintedModuleVersion)
+ return &blockedVersion
}
-
- break
}
}
return nil
}
-// IsBlockedPackage returns true if the package name is in
-// the blocked modules list.
-func (b BlockedModules) IsBlockedPackage(pkg string) bool {
- blockedModules := b.Get()
- for i := range blockedModules {
- if strings.HasPrefix(strings.ToLower(pkg), strings.ToLower(blockedModules[i])) {
- return true
+// BlockedModules a list of blocked modules.
+type BlockedModules []map[string]BlockedModule
+
+// Get returns the module names that are blocked.
+func (b BlockedModules) Get() []string {
+ modules := make([]string, len(b))
+
+ for n := range b {
+ for module := range b[n] {
+ modules[n] = module
+ break
}
}
- return false
+ return modules
}
-// IsBlockedModule returns true if the given module name is in the
-// blocked modules list.
-func (b BlockedModules) IsBlockedModule(module string) bool {
- blockedModules := b.Get()
- for i := range blockedModules {
- if strings.EqualFold(module, strings.TrimSpace(blockedModules[i])) {
- return true
+// GetBlockReason returns a block module if one is set for the provided linted module name.
+func (b BlockedModules) GetBlockReason(currentModuleName, lintedModuleName string) *BlockedModule {
+ for _, blockedModule := range b {
+ for blockedModuleName, blockedModule := range blockedModule {
+ if strings.EqualFold(strings.TrimSpace(lintedModuleName), strings.TrimSpace(blockedModuleName)) {
+ blockedModule.Set(currentModuleName)
+ return &blockedModule
+ }
}
}
- return false
+ return nil
}
// Allowed is a list of modules and module
@@ -145,10 +230,11 @@ type Allowed struct {
// IsAllowedModule returns true if the given module
// name is in the allowed modules list.
-func (a *Allowed) IsAllowedModule(module string) bool {
+func (a *Allowed) IsAllowedModule(moduleName string) bool {
allowedModules := a.Modules
+
for i := range allowedModules {
- if strings.EqualFold(module, strings.TrimSpace(allowedModules[i])) {
+ if strings.EqualFold(strings.TrimSpace(moduleName), strings.TrimSpace(allowedModules[i])) {
return true
}
}
@@ -158,10 +244,11 @@ func (a *Allowed) IsAllowedModule(module string) bool {
// IsAllowedModuleDomain returns true if the given modules domain is
// in the allowed module domains list.
-func (a *Allowed) IsAllowedModuleDomain(module string) bool {
+func (a *Allowed) IsAllowedModuleDomain(moduleName string) bool {
allowedDomains := a.Domains
+
for i := range allowedDomains {
- if strings.HasPrefix(strings.ToLower(module), strings.TrimSpace(strings.ToLower(allowedDomains[i]))) {
+ if strings.HasPrefix(strings.TrimSpace(strings.ToLower(moduleName)), strings.TrimSpace(strings.ToLower(allowedDomains[i]))) {
return true
}
}
@@ -172,7 +259,8 @@ func (a *Allowed) IsAllowedModuleDomain(module string) bool {
// Blocked is a list of modules that are
// blocked and not to be used.
type Blocked struct {
- Modules BlockedModules `yaml:"modules"`
+ Modules BlockedModules `yaml:"modules"`
+ Versions BlockedVersions `yaml:"versions"`
}
// Configuration of gomodguard allow and block lists.
@@ -192,46 +280,43 @@ type Result struct {
// String returns the filename, line
// number and reason of a Result.
func (r *Result) String() string {
- return fmt.Sprintf("%s:%d: %s", r.FileName, r.LineNumber, r.Reason)
+ return fmt.Sprintf("%s:%d:1 %s", r.FileName, r.LineNumber, r.Reason)
}
// Processor processes Go files.
type Processor struct {
- config Configuration
- logger *log.Logger
- modfile *modfile.File
- blockedModulesFromModFile []string
- result []Result
+ Config Configuration
+ Logger *log.Logger
+ Modfile *modfile.File
+ blockedModulesFromModFile map[string][]string
+ Result []Result
}
// NewProcessor will create a Processor to lint blocked packages.
func NewProcessor(config Configuration, logger *log.Logger) (*Processor, error) {
goModFileBytes, err := loadGoModFile()
if err != nil {
- errMsg := fmt.Sprintf("unable to read %s file: %s", goModFilename, err)
-
- return nil, fmt.Errorf(errMsg)
+ return nil, fmt.Errorf(errReadingGoModFile, goModFilename, err)
}
mfile, err := modfile.Parse(goModFilename, goModFileBytes, nil)
if err != nil {
- errMsg := fmt.Sprintf("unable to parse %s file: %s", goModFilename, err)
-
- return nil, fmt.Errorf(errMsg)
+ return nil, fmt.Errorf(errParsingGoModFile, goModFilename, err)
}
logger.Printf("info: allowed modules, %+v", config.Allowed.Modules)
logger.Printf("info: allowed module domains, %+v", config.Allowed.Domains)
logger.Printf("info: blocked modules, %+v", config.Blocked.Modules.Get())
+ logger.Printf("info: blocked modules with version constraints, %+v", config.Blocked.Versions.Get())
p := &Processor{
- config: config,
- logger: logger,
- modfile: mfile,
- result: []Result{},
+ Config: config,
+ Logger: logger,
+ Modfile: mfile,
+ Result: []Result{},
}
- p.setBlockedModulesFromModFile()
+ p.SetBlockedModulesFromModFile()
return p, nil
}
@@ -244,13 +329,18 @@ func (p *Processor) ProcessFiles(filenames []string) []Result {
pluralModuleMsg = ""
}
- p.logger.Printf("info: found `%d` blocked module%s in the %s file, %+v",
- len(p.blockedModulesFromModFile), pluralModuleMsg, goModFilename, p.blockedModulesFromModFile)
+ blockedModules := make([]string, 0, len(p.blockedModulesFromModFile))
+ for blockedModuleName := range p.blockedModulesFromModFile {
+ blockedModules = append(blockedModules, blockedModuleName)
+ }
+
+ p.Logger.Printf("info: found %d blocked module%s in %s: %+v",
+ len(p.blockedModulesFromModFile), pluralModuleMsg, goModFilename, blockedModules)
for _, filename := range filenames {
data, err := ioutil.ReadFile(filename)
if err != nil {
- p.result = append(p.result, Result{
+ p.Result = append(p.Result, Result{
FileName: filename,
LineNumber: 0,
Reason: fmt.Sprintf("unable to read file, file cannot be linted (%s)", err.Error()),
@@ -260,7 +350,7 @@ func (p *Processor) ProcessFiles(filenames []string) []Result {
p.process(filename, data)
}
- return p.result
+ return p.Result
}
// process file imports and add lint error if blocked package is imported.
@@ -269,7 +359,7 @@ func (p *Processor) process(filename string, data []byte) {
file, err := parser.ParseFile(fileSet, filename, data, parser.ParseComments)
if err != nil {
- p.result = append(p.result, Result{
+ p.Result = append(p.Result, Result{
FileName: filename,
LineNumber: 0,
Reason: fmt.Sprintf("invalid syntax, file cannot be linted (%s)", err.Error()),
@@ -279,23 +369,16 @@ func (p *Processor) process(filename string, data []byte) {
}
imports := file.Imports
- for i := range imports {
- importedPkg := strings.TrimSpace(strings.Trim(imports[i].Path.Value, "\""))
- if p.isBlockedPackageFromModFile(importedPkg) {
- reason := ""
-
- if p.config.Blocked.Modules.IsBlockedPackage(importedPkg) {
- reason = fmt.Sprintf(blockedReasonInBlockedList, importedPkg)
- } else {
- reason = fmt.Sprintf(blockedReasonNotInAllowedList, importedPkg)
- }
+ for n := range imports {
+ importedPkg := strings.TrimSpace(strings.Trim(imports[n].Path.Value, "\""))
- recommendedModules := p.config.Blocked.Modules.RecommendedModules(importedPkg)
- if recommendedModules != nil {
- reason += fmt.Sprintf(" %s", recommendedModules.String())
- }
+ blockReasons := p.isBlockedPackageFromModFile(importedPkg)
+ if blockReasons == nil {
+ continue
+ }
- p.addError(fileSet, imports[i].Pos(), reason)
+ for _, blockReason := range blockReasons {
+ p.addError(fileSet, imports[n].Pos(), blockReason)
}
}
}
@@ -305,7 +388,7 @@ func (p *Processor) process(filename string, data []byte) {
func (p *Processor) addError(fileset *token.FileSet, pos token.Pos, reason string) {
position := fileset.Position(pos)
- p.result = append(p.result, Result{
+ p.Result = append(p.Result, Result{
FileName: position.Filename,
LineNumber: position.Line,
Position: position,
@@ -313,64 +396,69 @@ func (p *Processor) addError(fileset *token.FileSet, pos token.Pos, reason strin
})
}
-// setBlockedModules determines which modules are blocked by reading
+// SetBlockedModulesFromModFile determines which modules are blocked by reading
// the go.mod file and comparing the require modules to the allowed modules.
-func (p *Processor) setBlockedModulesFromModFile() {
- blockedModules := make([]string, 0, len(p.modfile.Require))
- requiredModules := p.modfile.Require
- lintedModule := p.modfile.Module.Mod.Path
-
- for i := range requiredModules {
- if !requiredModules[i].Indirect {
- requiredModule := strings.TrimSpace(requiredModules[i].Mod.Path)
+func (p *Processor) SetBlockedModulesFromModFile() {
+ blockedModules := make(map[string][]string, len(p.Modfile.Require))
+ currentModuleName := p.Modfile.Module.Mod.Path
+ lintedModules := p.Modfile.Require
+
+ for i := range lintedModules {
+ if lintedModules[i].Indirect {
+ continue
+ }
- if p.config.Allowed.IsAllowedModuleDomain(requiredModule) {
- continue
- }
+ lintedModuleName := strings.TrimSpace(lintedModules[i].Mod.Path)
+ lintedModuleVersion := strings.TrimSpace(lintedModules[i].Mod.Version)
- if p.config.Allowed.IsAllowedModule(requiredModule) {
- continue
- }
+ var isAllowed bool
- requiredModuleIsBlocked := p.config.Blocked.Modules.IsBlockedModule(requiredModule)
+ switch {
+ case len(p.Config.Allowed.Modules) == 0 && len(p.Config.Allowed.Domains) == 0:
+ isAllowed = true
+ case p.Config.Allowed.IsAllowedModuleDomain(lintedModuleName):
+ isAllowed = true
+ case p.Config.Allowed.IsAllowedModule(lintedModuleName):
+ isAllowed = true
+ default:
+ isAllowed = false
+ }
- if len(p.config.Allowed.Modules) == 0 &&
- len(p.config.Allowed.Domains) == 0 &&
- !requiredModuleIsBlocked {
- continue
- }
+ blockModuleReason := p.Config.Blocked.Modules.GetBlockReason(currentModuleName, lintedModuleName)
+ blockVersionReason := p.Config.Blocked.Versions.GetBlockReason(lintedModuleName, lintedModuleVersion)
- // If the go.mod file being linted is a recommended module of a blocked module
- // and it imports that blocked module, do not set as a blocked. This means
- // that the linted module wraps that blocked module
- if requiredModuleIsBlocked {
- recommendedModules := p.config.Blocked.Modules.RecommendedModules(requiredModule)
+ if !isAllowed && blockModuleReason == nil && blockVersionReason == nil {
+ blockedModules[lintedModuleName] = append(blockedModules[lintedModuleName], blockReasonNotInAllowedList)
+ continue
+ }
- if recommendedModules.IsRecommended(lintedModule) {
- continue
- }
- }
+ if blockModuleReason != nil && !blockModuleReason.IsAllowed() {
+ blockedModules[lintedModuleName] = append(blockedModules[lintedModuleName], fmt.Sprintf("%s %s", blockReasonInBlockedList, blockModuleReason.Message()))
+ }
- blockedModules = append(blockedModules, requiredModule)
+ if blockVersionReason != nil && !blockVersionReason.IsAllowed() {
+ blockedModules[lintedModuleName] = append(blockedModules[lintedModuleName], fmt.Sprintf("%s %s", blockReasonInBlockedList, blockVersionReason.Message()))
}
}
- if len(blockedModules) > 0 {
- p.blockedModulesFromModFile = blockedModules
- }
+ p.blockedModulesFromModFile = blockedModules
}
-// isBlockedPackageFromModFile returns true if the imported packages
-// module is in the go.mod file and was blocked.
-func (p *Processor) isBlockedPackageFromModFile(pkg string) bool {
- blockedModulesFromModFile := p.blockedModulesFromModFile
- for i := range blockedModulesFromModFile {
- if strings.HasPrefix(strings.ToLower(pkg), strings.ToLower(blockedModulesFromModFile[i])) {
- return true
+// isBlockedPackageFromModFile returns the block reason if the package is blocked.
+func (p *Processor) isBlockedPackageFromModFile(packageName string) []string {
+ for blockedModuleName, blockReasons := range p.blockedModulesFromModFile {
+ if strings.HasPrefix(strings.TrimSpace(packageName), strings.TrimSpace(blockedModuleName)) {
+ formattedReasons := make([]string, 0, len(blockReasons))
+
+ for _, blockReason := range blockReasons {
+ formattedReasons = append(formattedReasons, fmt.Sprintf(blockReason, packageName))
+ }
+
+ return formattedReasons
}
}
- return false
+ return nil
}
func loadGoModFile() ([]byte, error) {
@@ -386,6 +474,7 @@ func loadGoModFile() ([]byte, error) {
_, _ = buf.ReadFrom(stdout)
goEnv := make(map[string]string)
+
err := json.Unmarshal(buf.Bytes(), &goEnv)
if err != nil {
return ioutil.ReadFile(goModFilename)