зеркало из https://github.com/golang/pkgsite.git
internal: remove unit-meta-with-latest experiment
For golang/go#43265 Change-Id: I1d056a893fdff60744ff328ab9f4a1b6665b3e32 Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/309709 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>
This commit is contained in:
Родитель
58432cb4a0
Коммит
103f9ede54
|
@ -9,7 +9,6 @@ const (
|
|||
ExperimentInsertSymbols = "insert-symbols"
|
||||
ExperimentSymbolHistoryVersionsPage = "symbol-history-versions-page"
|
||||
ExperimentSymbolHistoryMainPage = "symbol-history-main-page"
|
||||
ExperimentUnitMetaWithLatest = "unit-meta-with-latest"
|
||||
)
|
||||
|
||||
// Experiments represents all of the active experiments in the codebase and
|
||||
|
@ -18,7 +17,6 @@ var Experiments = map[string]string{
|
|||
ExperimentInsertSymbols: "Insert data into symbols, package_symbols, and documentation_symbols.",
|
||||
ExperimentSymbolHistoryVersionsPage: "Show package API history on the versions page.",
|
||||
ExperimentSymbolHistoryMainPage: "Show package API history on the main unit page.",
|
||||
ExperimentUnitMetaWithLatest: "Use latest-version information for GetUnitMeta.",
|
||||
}
|
||||
|
||||
// Experiment holds data associated with an experimental feature for frontend
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"golang.org/x/pkgsite/internal"
|
||||
"golang.org/x/pkgsite/internal/database"
|
||||
"golang.org/x/pkgsite/internal/derrors"
|
||||
"golang.org/x/pkgsite/internal/experiment"
|
||||
"golang.org/x/pkgsite/internal/middleware"
|
||||
"golang.org/x/pkgsite/internal/stdlib"
|
||||
"golang.org/x/pkgsite/internal/version"
|
||||
|
@ -39,19 +38,16 @@ func (db *DB) GetUnitMeta(ctx context.Context, fullPath, requestedModulePath, re
|
|||
defer derrors.WrapStack(&err, "DB.GetUnitMeta(ctx, %q, %q, %q)", fullPath, requestedModulePath, requestedVersion)
|
||||
defer middleware.ElapsedStat(ctx, "GetUnitMeta")()
|
||||
|
||||
if experiment.IsActive(ctx, internal.ExperimentUnitMetaWithLatest) {
|
||||
modulePath := requestedModulePath
|
||||
version := requestedVersion
|
||||
var lmv *internal.LatestModuleVersions
|
||||
if requestedVersion == internal.LatestVersion {
|
||||
modulePath, version, lmv, err = db.getLatestUnitVersion(ctx, fullPath, requestedModulePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
modulePath := requestedModulePath
|
||||
version := requestedVersion
|
||||
var lmv *internal.LatestModuleVersions
|
||||
if requestedVersion == internal.LatestVersion {
|
||||
modulePath, version, lmv, err = db.getLatestUnitVersion(ctx, fullPath, requestedModulePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db.getUnitMetaWithKnownLatestVersion(ctx, fullPath, modulePath, version, lmv)
|
||||
}
|
||||
return db.legacyGetUnitMeta(ctx, fullPath, requestedModulePath, requestedVersion)
|
||||
return db.getUnitMetaWithKnownLatestVersion(ctx, fullPath, modulePath, version, lmv)
|
||||
}
|
||||
|
||||
func (db *DB) getUnitMetaWithKnownLatestVersion(ctx context.Context, fullPath, modulePath, version string, lmv *internal.LatestModuleVersions) (_ *internal.UnitMeta, err error) {
|
||||
|
@ -225,131 +221,6 @@ func (db *DB) getLatestUnitVersion(ctx context.Context, fullPath, requestedModul
|
|||
return modulePath, latestVersion, nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) legacyGetUnitMeta(ctx context.Context, fullPath, requestedModulePath, requestedVersion string) (_ *internal.UnitMeta, err error) {
|
||||
defer derrors.WrapStack(&err, "DB.legacyGetUnitMeta(ctx, %q, %q, %q)", fullPath, requestedModulePath, requestedVersion)
|
||||
|
||||
var (
|
||||
q string
|
||||
args []interface{}
|
||||
)
|
||||
q, args, err = getUnitMetaQuery(fullPath, requestedModulePath, requestedVersion).PlaceholderFormat(squirrel.Dollar).ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("squirrel.ToSql: %v", err)
|
||||
}
|
||||
var (
|
||||
licenseTypes []string
|
||||
licensePaths []string
|
||||
um = internal.UnitMeta{Path: fullPath}
|
||||
)
|
||||
err = db.db.QueryRow(ctx, q, args...).Scan(
|
||||
&um.ModulePath,
|
||||
&um.Version,
|
||||
&um.CommitTime,
|
||||
jsonbScanner{&um.SourceInfo},
|
||||
&um.HasGoMod,
|
||||
&um.ModuleInfo.IsRedistributable,
|
||||
&um.Name,
|
||||
&um.IsRedistributable,
|
||||
pq.Array(&licenseTypes),
|
||||
pq.Array(&licensePaths))
|
||||
switch err {
|
||||
case sql.ErrNoRows:
|
||||
return nil, derrors.NotFound
|
||||
case nil:
|
||||
lics, err := zipLicenseMetadata(licenseTypes, licensePaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if db.bypassLicenseCheck {
|
||||
um.IsRedistributable = true
|
||||
}
|
||||
|
||||
um.Licenses = lics
|
||||
if err := populateLatestInfo(ctx, db, &um.ModuleInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &um, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func getUnitMetaQuery(fullPath, requestedModulePath, requestedVersion string) squirrel.SelectBuilder {
|
||||
query := squirrel.Select(
|
||||
"m.module_path",
|
||||
"m.version",
|
||||
"m.commit_time",
|
||||
"m.source_info",
|
||||
"m.has_go_mod",
|
||||
"m.redistributable",
|
||||
"u.name",
|
||||
"u.redistributable",
|
||||
"u.license_types",
|
||||
"u.license_paths",
|
||||
)
|
||||
if requestedVersion != internal.LatestVersion {
|
||||
query = query.From("modules m").
|
||||
Join("units u on u.module_id = m.id").
|
||||
Join("paths p ON p.id = u.path_id").Where(squirrel.Eq{"p.path": fullPath})
|
||||
if requestedModulePath != internal.UnknownModulePath {
|
||||
query = query.Where(squirrel.Eq{"m.module_path": requestedModulePath})
|
||||
}
|
||||
if internal.DefaultBranches[requestedVersion] {
|
||||
query = query.Join("version_map vm ON m.id = vm.module_id").Where("vm.requested_version = ? ", requestedVersion)
|
||||
} else if requestedVersion != internal.LatestVersion {
|
||||
query = query.Where(squirrel.Eq{"version": requestedVersion})
|
||||
}
|
||||
return orderByLatest(query).Limit(1)
|
||||
}
|
||||
|
||||
// Use a nested select to fetch the latest version of the unit, then JOIN
|
||||
// on units to fetch other relevant information. This allows us to use the
|
||||
// index on units.id and paths.path to get the latest path. We can then
|
||||
// look up only the relevant information from the units table.
|
||||
nestedSelect := orderByLatest(squirrel.Select(
|
||||
"m.id",
|
||||
"m.module_path",
|
||||
"m.version",
|
||||
"m.commit_time",
|
||||
"m.source_info",
|
||||
"m.has_go_mod",
|
||||
"m.redistributable",
|
||||
"u.id AS unit_id",
|
||||
).From("modules m").
|
||||
Join("units u ON u.module_id = m.id").
|
||||
Join("paths p ON p.id = u.path_id").
|
||||
Where(squirrel.Eq{"p.path": fullPath}))
|
||||
if requestedModulePath != internal.UnknownModulePath {
|
||||
nestedSelect = nestedSelect.Where(squirrel.Eq{"m.module_path": requestedModulePath})
|
||||
}
|
||||
nestedSelect = nestedSelect.Limit(1)
|
||||
return query.From("units u").JoinClause(nestedSelect.Prefix("JOIN (").Suffix(") m ON u.id = m.unit_id"))
|
||||
}
|
||||
|
||||
// orderByLatest orders paths according to the go command.
|
||||
// Versions are ordered by:
|
||||
// (1) release (non-incompatible)
|
||||
// (2) prerelease (non-incompatible)
|
||||
// (3) release, incompatible
|
||||
// (4) prerelease, incompatible
|
||||
// (5) pseudo
|
||||
// They are then sorted based on semver, then decreasing module path length (so
|
||||
// that nested modules are preferred).
|
||||
func orderByLatest(q squirrel.SelectBuilder) squirrel.SelectBuilder {
|
||||
return q.OrderBy(
|
||||
`CASE
|
||||
WHEN m.version_type = 'release' AND NOT m.incompatible THEN 1
|
||||
WHEN m.version_type = 'prerelease' AND NOT m.incompatible THEN 2
|
||||
WHEN m.version_type = 'release' THEN 3
|
||||
WHEN m.version_type = 'prerelease' THEN 4
|
||||
ELSE 5
|
||||
END`,
|
||||
"m.series_path DESC",
|
||||
"m.sort_version DESC",
|
||||
).PlaceholderFormat(squirrel.Dollar)
|
||||
}
|
||||
|
||||
// GetUnit returns a unit from the database, along with all of the data
|
||||
// associated with that unit.
|
||||
func (db *DB) GetUnit(ctx context.Context, um *internal.UnitMeta, fields internal.FieldSet) (_ *internal.Unit, err error) {
|
||||
|
|
|
@ -26,12 +26,7 @@ func TestGetUnitMeta(t *testing.T) {
|
|||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout*2)
|
||||
defer cancel()
|
||||
t.Run("legacy", func(t *testing.T) {
|
||||
testGetUnitMeta(t, ctx)
|
||||
})
|
||||
t.Run("latest", func(t *testing.T) {
|
||||
testGetUnitMeta(t, experiment.NewContext(ctx, internal.ExperimentUnitMetaWithLatest))
|
||||
})
|
||||
testGetUnitMeta(t, ctx)
|
||||
}
|
||||
|
||||
func testGetUnitMeta(t *testing.T, ctx context.Context) {
|
||||
|
@ -207,104 +202,6 @@ func testGetUnitMeta(t *testing.T, ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetUnitMetaDiffs(t *testing.T) {
|
||||
// Demonstrate differences between legacy and latest-version GetUnitMeta
|
||||
// implementations.
|
||||
|
||||
t.Parallel()
|
||||
|
||||
type latest struct { // latest-version info
|
||||
module string
|
||||
version string // latest raw and cooked version
|
||||
goMod string // go.mod file contents after "module" line
|
||||
}
|
||||
|
||||
modver := func(u *internal.UnitMeta) string { return u.ModulePath + "@" + u.Version }
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
packages []string // mod@ver/pkg
|
||||
latests []latest
|
||||
path string
|
||||
wantLatest, wantLegacy string
|
||||
}{
|
||||
{
|
||||
name: "incompatible",
|
||||
// When there are incompatible versions and no go.mod at the latest
|
||||
// compatible version, the go command selects the highest
|
||||
// incompatible version, but legacy GetUnitMeta selects the highest
|
||||
// compatible version.
|
||||
packages: []string{
|
||||
"m.com@v1.0.0/a",
|
||||
"m.com@v2.0.0+incompatible/a",
|
||||
},
|
||||
latests: []latest{{"m.com", "v2.0.0+incompatible", ""}},
|
||||
path: "m.com/a",
|
||||
wantLatest: "m.com@v2.0.0+incompatible",
|
||||
wantLegacy: "m.com@v1.0.0",
|
||||
},
|
||||
{
|
||||
name: "shorter",
|
||||
// The go command prefers the longer path if both have latest-version information,
|
||||
// but legacy GetUnitMeta prefers the shorter path if it has a release version.
|
||||
packages: []string{
|
||||
"m.com@v1.0.0/a/b", // shorter path, release version
|
||||
"m.com/a@v1.0.0-pre/b", // longer path, pre-release version
|
||||
},
|
||||
latests: []latest{{"m.com", "v1.0.0", ""}, {"m.com/a", "v1.0.0-pre", ""}},
|
||||
path: "m.com/a/b",
|
||||
wantLatest: "m.com/a@v1.0.0-pre",
|
||||
wantLegacy: "m.com@v1.0.0",
|
||||
},
|
||||
{
|
||||
name: "retraction",
|
||||
// Legacy GetUnitMeta ignores retractions when picking the latest version.
|
||||
packages: []string{
|
||||
"m.com@v1.0.0/a",
|
||||
"m.com@v1.1.0/a", // latest, also retracted
|
||||
},
|
||||
latests: []latest{{"m.com", "v1.1.0", "retract v1.1.0"}},
|
||||
path: "m.com/a",
|
||||
wantLatest: "m.com@v1.0.0",
|
||||
wantLegacy: "m.com@v1.1.0",
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
testDB, release := acquire(t)
|
||||
defer release()
|
||||
|
||||
for _, p := range test.packages {
|
||||
mod, ver, pkg := parseModuleVersionPackage(p)
|
||||
m := sample.Module(mod, ver, pkg)
|
||||
goMod := "module " + mod
|
||||
for _, l := range test.latests {
|
||||
if l.module == mod && l.version == ver {
|
||||
goMod += "\n" + l.goMod
|
||||
break
|
||||
}
|
||||
}
|
||||
MustInsertModuleGoMod(ctx, t, testDB, m, goMod)
|
||||
}
|
||||
gotLegacy, err := testDB.GetUnitMeta(ctx, test.path, internal.UnknownModulePath, internal.LatestVersion)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := modver(gotLegacy); got != test.wantLegacy {
|
||||
t.Errorf("legacy: got %s, want %s", got, test.wantLegacy)
|
||||
}
|
||||
gotLatest, err := testDB.GetUnitMeta(experiment.NewContext(ctx, internal.ExperimentUnitMetaWithLatest),
|
||||
test.path, internal.UnknownModulePath, internal.LatestVersion)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := modver(gotLatest); got != test.wantLatest {
|
||||
t.Errorf("latest: got %s, want %s", got, test.wantLatest)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUnitMetaBypass(t *testing.T) {
|
||||
t.Parallel()
|
||||
testDB, release := acquire(t)
|
||||
|
@ -318,13 +215,13 @@ func TestGetUnitMetaBypass(t *testing.T) {
|
|||
module, version, packageSuffix string
|
||||
isMaster bool
|
||||
}{
|
||||
{"m.com", "v2.0.0+incompatible", "a", false},
|
||||
{"m.com/b", "v2.0.0+incompatible", "a", true},
|
||||
{"m.com", "v1.0.0", "a", false},
|
||||
{"m.com", "v1.0.1", "dir/a", false},
|
||||
{"m.com", "v1.1.0", "a/b", false},
|
||||
{"m.com", "v1.2.0-pre", "a", true},
|
||||
{"m.com", "v2.0.0+incompatible", "a", false},
|
||||
{"m.com/a", "v1.1.0", "b", false},
|
||||
{"m.com/b", "v2.0.0+incompatible", "a", true},
|
||||
} {
|
||||
m := sample.Module(testModule.module, testModule.version, testModule.packageSuffix)
|
||||
makeModuleNonRedistributable(m)
|
||||
|
|
Загрузка…
Ссылка в новой задаче