From abc6380311993c92d569df45c160aae5767b7032 Mon Sep 17 00:00:00 2001 From: David Fleming Date: Tue, 26 Jul 2022 22:36:32 -0400 Subject: [PATCH] fix: incorrectly blocking versioned modules --- gomodguard.go | 12 ++++++++++++ internal_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 internal_test.go diff --git a/gomodguard.go b/gomodguard.go index 7ef4623..e2107ec 100644 --- a/gomodguard.go +++ b/gomodguard.go @@ -10,6 +10,7 @@ import ( "io/ioutil" "os" "os/exec" + "regexp" "strings" "github.com/Masterminds/semver" @@ -30,6 +31,10 @@ var ( "blocked modules list." blockReasonHasLocalReplaceDirective = "import of package `%s` is blocked because the module has a " + "local replace directive." + + // startsWithVersion is used to test when a string begins with the version identifier of a module, after having stripped the prefix base module name + // ie "github.com/foo/bar/v2/baz" => "/v2/baz" probably indicates that the module is actually github.com/foo/bar/v2, not github.com/foo/bar + startsWithVersion = regexp.MustCompile(`^\/v[0-9]+`) ) // BlockedVersion has a version constraint a reason why the the module version is blocked. @@ -438,6 +443,13 @@ func (p *Processor) SetBlockedModules() { //nolint:gocognit,funlen func (p *Processor) isBlockedPackageFromModFile(packageName string) []string { for blockedModuleName, blockReasons := range p.blockedModulesFromModFile { if strings.HasPrefix(strings.TrimSpace(packageName), strings.TrimSpace(blockedModuleName)) { + // Test if a versioned module matched its base version + // ie github.com/foo/bar/v2 matched github.com/foo/bar, even though the former may be allowed. + suffix := strings.TrimPrefix(strings.TrimSpace(packageName), strings.TrimSpace(blockedModuleName)) + if startsWithVersion.MatchString(suffix) { + continue + } + formattedReasons := make([]string, 0, len(blockReasons)) for _, blockReason := range blockReasons { diff --git a/internal_test.go b/internal_test.go new file mode 100644 index 0000000..849d115 --- /dev/null +++ b/internal_test.go @@ -0,0 +1,31 @@ +package gomodguard + +import "testing" + +func TestIsModuleBlocked(t *testing.T) { + var tests = []struct { + testName string + processor Processor + testModule string + }{ + { + "previous version blocked", + Processor{ + blockedModulesFromModFile: map[string][]string{ + "github.com/foo/bar": {blockReasonNotInAllowedList}, + }, + }, + "github.com/foo/bar/v2", + }, + } + + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + blockReasons := tt.processor.isBlockedPackageFromModFile(tt.testModule) + if len(blockReasons) > 0 { + t.Logf("Testing %v, expected allowed, was blocked: %v", tt.testModule, blockReasons) + t.Fail() + } + }) + } +}