aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorMadeline Kalil <mkalil@google.com>2026-03-31 13:34:41 -0400
committerMadeline Kalil <mkalil@google.com>2026-04-08 07:19:42 -0700
commit5c3cacb5982231e5d4acd75f6c4cf1bb8f7ba411 (patch)
tree3641b80eb19d692f8823f213e3a8e3562361c6c0 /internal
parentf1e456b85e628969cdc65e0fec050038e653d1a0 (diff)
downloadgo-x-pkgsite-5c3cacb5982231e5d4acd75f6c4cf1bb8f7ba411.tar.xz
internal/postgres: allow matching exact prefix with exact:
Currently, the package exclusion process is case insensitive, because certain hosts such as GitHub are case insensitive. The only way to exclude a case sensitive version without also excluding all case insensitive matches is to add the prefix to caseSensitiveExcludedPaths in internal/frontend/details.go. This CL implements a new approach to excluding case sensitive paths: it enables specifying an "exact:" prefix in excluded.txt that will force matching the pattern exactly, instead of with case insensitivity. For golang/go#77822 Change-Id: I123ad2e13ff6673084006c6d51377308d95230ce Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/761521 kokoro-CI: kokoro <noreply+kokoro@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ethan Lee <ethanalee@google.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/frontend/details.go2
-rw-r--r--internal/postgres/excluded.go26
-rw-r--r--internal/postgres/excluded_test.go13
3 files changed, 29 insertions, 12 deletions
diff --git a/internal/frontend/details.go b/internal/frontend/details.go
index 27b40f05..f1438de4 100644
--- a/internal/frontend/details.go
+++ b/internal/frontend/details.go
@@ -103,6 +103,8 @@ func checkExcluded(ctx context.Context, ds internal.DataSource, fullPath, versio
// Paths to exclude if they match exactly.
// These are very rare, so it's simpler to hardcode them rather than use the DB.
+// TODO(mkalil): Remove once go.dev/cl/761521, which provides an alternative
+// implementation for case sensitive exclusions, is merged.
var caseSensitiveExcludedPaths = map[string]bool{
"github.com/ibm/sarama": true, // https://go.dev/issue/71342
"github.com/burntsushi/toml": true, // https://go.dev/issue/68357
diff --git a/internal/postgres/excluded.go b/internal/postgres/excluded.go
index 176b9c7e..6225c6b3 100644
--- a/internal/postgres/excluded.go
+++ b/internal/postgres/excluded.go
@@ -31,22 +31,28 @@ func (db *DB) IsExcluded(ctx context.Context, path, version string) bool {
func excludes(pattern, path, version string) bool {
// Certain hosts (such as GitHub) are case insensitive.
- // Therefore, we err on the side of insensitive exclusions.
+ // By default, we err on the side of insensitive exclusions.
+ // If the pattern starts with "exact:", we match exactly (case sensitive).
+ isExact := strings.HasPrefix(pattern, "exact:")
+ if isExact {
+ pattern = pattern[len("exact:"):]
+ }
- // Patterns with "@" must match the full path (case insensitively).
mod, ver, found := strings.Cut(pattern, "@")
if found {
+ if isExact {
+ return mod == path && ver == version
+ }
return strings.EqualFold(mod, path) && ver == version
}
- // Patterns without "@" can match the full path or be a componentwise prefix
- // (case insensitively).
- if strings.EqualFold(pattern, path) {
- return true
- }
- if !strings.HasSuffix(pattern, "/") {
- pattern += "/"
+
+ pattern = strings.TrimSuffix(pattern, "/")
+
+ if isExact {
+ return pattern == path || strings.HasPrefix(path, pattern+"/")
}
- return strings.HasPrefix(strings.ToLower(path), strings.ToLower(pattern))
+ return strings.EqualFold(pattern, path) ||
+ strings.HasPrefix(strings.ToLower(path), strings.ToLower(pattern)+"/")
}
// InsertExcludedPattern inserts pattern into the excluded_prefixes table.
diff --git a/internal/postgres/excluded_test.go b/internal/postgres/excluded_test.go
index 13206a85..e8050aee 100644
--- a/internal/postgres/excluded_test.go
+++ b/internal/postgres/excluded_test.go
@@ -15,7 +15,7 @@ func TestIsExcluded(t *testing.T) {
defer release()
ctx := context.Background()
- for _, pat := range []string{"bad", "badslash/", "baddy@v1.2.3", "github.com/bad"} {
+ for _, pat := range []string{"bad", "badslash/", "baddy@v1.2.3", "github.com/bad", "exact:github.com/CASE/go", "exact:github.com/PACKAGE@v1.0.0"} {
if err := testDB.InsertExcludedPattern(ctx, pat, "someone", "because"); err != nil {
t.Fatal(err)
}
@@ -31,7 +31,7 @@ func TestIsExcluded(t *testing.T) {
{"badness", "", false},
{"bad/ness", "", true},
{"bad.com/foo", "", false},
- {"badslash", "", false},
+ {"badslash", "", true},
{"badslash/more", "", true},
{"badslash/more", "v1.2.3", true},
{"baddys", "v1.2.3", false},
@@ -48,6 +48,15 @@ func TestIsExcluded(t *testing.T) {
{"github.com/bad/repo", "", true},
{"github.com/bad/Repo", "", true},
{"github.com/Bad/repo", "", true},
+
+ // tests for exact: prefix
+ {"github.com/CASE/go", "", true},
+ {"github.com/case/go", "", false},
+ {"github.com/CASE/go/sub", "", true},
+ {"github.com/case/go/sub", "", false},
+ {"github.com/PACKAGE", "v1.0.0", true},
+ {"github.com/package", "v1.0.0", false},
+ {"github.com/PACKAGE", "v1.0.1", false},
} {
got := testDB.IsExcluded(ctx, test.path, test.version)
if got != test.want {