internal/search: fix stdlib grouping
Fix a bug that resulted in net/http/prof not being grouped with
net/http.
The bug arose from a mistake in extracting the top-level directory
from a stdlib package path. After coming across the proposal for
`strings.Cut` (https://golang.org/issue/46336), I was on the fence
about adding a copy to this repo and using it here. Ultimately I
decided that the job was simple enough to do without it.
I was wrong. So this CL adds `Cut` and uses it here. We can
incremently use it in other places where it simplifies things.
Change-Id: I804aea93f3850bba52d9e0edde8ea136746093f8
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/347555
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/postgres/search.go b/internal/postgres/search.go
index 359c113..6cbf43e 100644
--- a/internal/postgres/search.go
+++ b/internal/postgres/search.go
@@ -9,7 +9,6 @@
"database/sql"
"fmt"
"io"
- "path"
"sort"
"strings"
"time"
@@ -591,11 +590,8 @@
// Packages in the standard library are grouped by their top-level
// directory, and we can consider them all part of the same major version.
if r.ModulePath == stdlib.ModulePath {
- dir := r.PackagePath
- if strings.ContainsRune(dir, '/') {
- dir = path.Dir(dir)
- }
- return dir, 1
+ before, _, _ := internal.Cut(r.PackagePath, "/")
+ return before, 1
}
return internal.SeriesPathAndMajorVersion(r.ModulePath)
}
diff --git a/internal/postgres/search_test.go b/internal/postgres/search_test.go
index 02a0cba..e942b14 100644
--- a/internal/postgres/search_test.go
+++ b/internal/postgres/search_test.go
@@ -1458,6 +1458,25 @@
}},
},
},
+ {
+ name: "stdlib 2",
+ in: []*SearchResult{
+ {PackagePath: "m1", ModulePath: "m1", Version: "v0.0.0", Score: 9},
+ {PackagePath: "net/http", ModulePath: stdlib.ModulePath, Score: 8},
+ {PackagePath: "encoding/json", ModulePath: stdlib.ModulePath, Score: 7},
+ {PackagePath: "encoding/gob", ModulePath: stdlib.ModulePath, Score: 6},
+ {PackagePath: "net/http/prof", ModulePath: stdlib.ModulePath, Score: 5},
+ },
+ want: []*SearchResult{
+ {PackagePath: "m1", ModulePath: "m1", Version: "v0.0.0", Score: 9},
+ {PackagePath: "net/http", ModulePath: stdlib.ModulePath, Score: 8, SameModule: []*SearchResult{
+ {PackagePath: "net/http/prof", ModulePath: stdlib.ModulePath, Score: 5},
+ }},
+ {PackagePath: "encoding/json", ModulePath: stdlib.ModulePath, Score: 7, SameModule: []*SearchResult{
+ {PackagePath: "encoding/gob", ModulePath: stdlib.ModulePath, Score: 6},
+ }},
+ },
+ },
} {
t.Run(test.name, func(t *testing.T) {
got := groupSearchResults(test.in)
diff --git a/internal/util.go b/internal/util.go
index a803139..eb7f9bc 100644
--- a/internal/util.go
+++ b/internal/util.go
@@ -37,3 +37,18 @@
}
return lines, nil
}
+
+// Cut cuts s around the first instance of sep,
+// returning the text before and after sep.
+// The found result reports whether sep appears in s.
+// If sep does not appear in s, cut returns s, "", false.
+//
+// https://golang.org/issue/46336 is an accepted proposal to add this to the
+// standard library. It will presumably land in Go 1.18, so this can be removed
+// when pkgsite moves to that version.
+func Cut(s, sep string) (before, after string, found bool) {
+ if i := strings.Index(s, sep); i >= 0 {
+ return s[:i], s[i+len(sep):], true
+ }
+ return s, "", false
+}