Skip to content

Commit dd385e7

Browse files
committed
internal/postgres: change versions sort order
In getPath versions, sort first by version,then by module path. Module path came first in order to group results by module when a package appears in more than one module. But it also results in out-of-order versions, because v11 sorts before v2. Now we only use the module path to break ties when versions are the same. Incompatible versions still come last. Fixes #79632. Change-Id: I1b66135685a0b36478bb0380da03e515ae64b4cb Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/784460 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com> kokoro-CI: kokoro <noreply+kokoro@google.com>
1 parent e5e6f65 commit dd385e7

2 files changed

Lines changed: 65 additions & 10 deletions

File tree

internal/postgres/version.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,12 @@ func getPathVersions(ctx context.Context, db *DB, path string, startPageToken st
9494
LIMIT 1
9595
)
9696
AND version_type in (%s)
97-
AND ($3 = '' OR (NOT m.incompatible, m.module_path, m.sort_version) <= (NOT $2, $3, $4))
97+
AND ($3 = '' OR (NOT m.incompatible, m.sort_version, m.module_path) <= (NOT $2, $3, $4))
9898
ORDER BY
9999
m.incompatible,
100-
m.module_path DESC,
101-
m.sort_version DESC %s`
100+
m.sort_version DESC,
101+
m.module_path DESC
102+
%s`
102103

103104
if len(versionTypes) == 0 {
104105
return nil, "", fmt.Errorf("error: must specify at least one version type")
@@ -132,17 +133,18 @@ func getPathVersions(ctx context.Context, db *DB, path string, startPageToken st
132133
// Construct the page token for the next page.
133134
// See the comment near the top of this function for the format.
134135
if len(versions) > 0 {
135-
nextPageToken = makePageToken(lastIncompatible, versions[len(versions)-1].ModulePath, lastSortVersion)
136+
nextPageToken = makePageToken(lastIncompatible, lastSortVersion, versions[len(versions)-1].ModulePath)
136137
}
137138
return versions, nextPageToken, nil
138139
}
139140

140141
// parsePageToken parses a page token for getPathVersions.
141142
// It return a slice of query args.
142143
func parsePageToken(s string) (queryArgs []any, err error) {
143-
// A page token has the form "I P S"
144-
// where I is a bool for incompatible version, P is a module path, and S
145-
// is a sort version. Spaces suffice to separate these since none can contain a space.
144+
// A page token has the form "I S P"
145+
// where I is a bool for incompatible version, S
146+
// is a sort version and P is a module path.
147+
// Spaces suffice to separate these since none can contain a space.
146148
parts := strings.Fields(s)
147149
if len(parts) != 3 {
148150
return nil, errors.New("invalid page token (wrong # parts)")
@@ -155,8 +157,8 @@ func parsePageToken(s string) (queryArgs []any, err error) {
155157
}
156158

157159
// makePageToken constructs a page token for getPathVersions.
158-
func makePageToken(inc bool, mpath, version string) string {
159-
return fmt.Sprintf("%t %s %s", inc, mpath, version)
160+
func makePageToken(inc bool, version, mpath string) string {
161+
return fmt.Sprintf("%t %s %s", inc, version, mpath)
160162
}
161163

162164
// versionTypeExpr returns a comma-separated list of version types,

internal/postgres/version_test.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
"golang.org/x/pkgsite/internal/version"
2020
)
2121

22-
func TestGetVersions(t *testing.T) {
22+
func TestGetVersionsForPath(t *testing.T) {
2323
t.Parallel()
2424
var (
2525
taggedAndPseudoModule = "path.to/foo"
@@ -266,6 +266,59 @@ func TestGetVersions(t *testing.T) {
266266
}
267267
}
268268

269+
func TestGetPathVersionsSorting(t *testing.T) {
270+
// Validate that getPathVersions sorts by version,
271+
// then by module path, with incompatible versions last.
272+
testDB, release := acquire(t)
273+
defer release()
274+
testModules := []*internal.Module{
275+
sample.Module("m.com/a", "v1.0.0", "pkg"),
276+
sample.Module("m.com/a", "v1.2.3", "pkg"),
277+
sample.Module("m.com/a", "v1.2.3-pre", "pkg"),
278+
sample.Module("m.com/a", "v2.1.1+incompatible", "pkg"),
279+
sample.Module("m.com/a", "v2.2.2+incompatible", "pkg"),
280+
sample.Module("m.com/a", "v0.0.0-20200101120012-000000000000", "pkg"),
281+
sample.Module("m.com/a/v2", "v2.2.2", "pkg"),
282+
sample.Module("m.com/a/v2", "v2.1.1", "pkg"),
283+
sample.Module("m.com/a/v11", "v11.0.0", "pkg"),
284+
// same package path, different module
285+
sample.Module("m.com", "v1.2.3", "a/pkg"),
286+
sample.Module("m.com", "v1.3.0", "a/pkg"),
287+
}
288+
for _, m := range testModules {
289+
testDB.MustInsertModule(t, m)
290+
}
291+
gotmods, _, err := getPathVersions(t.Context(), testDB, "m.com/a", "", 0, version.TypePrerelease, version.TypeRelease, version.TypePseudo)
292+
if err != nil {
293+
t.Fatal(err)
294+
}
295+
296+
type modver struct {
297+
ModulePath, Version string
298+
}
299+
want := []modver{
300+
{"m.com/a/v11", "v11.0.0"},
301+
{"m.com/a/v2", "v2.2.2"},
302+
{"m.com/a/v2", "v2.1.1"},
303+
{"m.com", "v1.3.0"},
304+
// version ties are broken by module path
305+
{"m.com/a", "v1.2.3"},
306+
{"m.com", "v1.2.3"},
307+
{"m.com/a", "v1.2.3-pre"},
308+
{"m.com/a", "v1.0.0"},
309+
{"m.com/a", "v0.0.0-20200101120012-000000000000"},
310+
{"m.com/a", "v2.2.2+incompatible"},
311+
{"m.com/a", "v2.1.1+incompatible"},
312+
}
313+
var got []modver
314+
for _, mi := range gotmods {
315+
got = append(got, modver{mi.ModulePath, mi.Version})
316+
}
317+
if diff := cmp.Diff(want, got); diff != "" {
318+
t.Errorf("mismatch (-want, +got):\n%s", diff)
319+
}
320+
}
321+
269322
func TestGetLatestInfo(t *testing.T) {
270323
t.Parallel()
271324
testDB, release := acquire(t)

0 commit comments

Comments
 (0)