internal/frontend: add internal.PackageMeta

The two functions for creating a frontend.Package, legacyCreatePackage
and createPackageNew, are merged into a single createPackage function.

createPackage uses the new PackageMeta type, as input. It does not take
any legacy structs as input and returns a frontend.Package.

In future CLs, PackageMeta will be used to LegacyDirectory, when
fetching data for the directories tab.

For golang/go#39629

Change-Id: I80ec5272c6f8e237f0752938a89c633e3a1b81f5
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/241441
Reviewed-by: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Julie Qiu 2020-07-08 23:11:24 -04:00
Родитель 3aae7e77f9
Коммит 8ac8ac1779
6 изменённых файлов: 71 добавлений и 74 удалений

Просмотреть файл

@ -111,8 +111,7 @@ type VersionedDirectory struct {
ModuleInfo
}
// DirectoryMeta represents a folder in a module version, and the metadata
// associated with that folder.
// DirectoryMeta represents the metadata of a directory in a module version.
type DirectoryMeta struct {
Path string
V1Path string
@ -120,7 +119,7 @@ type DirectoryMeta struct {
Licenses []*licenses.Metadata // metadata of applicable licenses
}
// DirectoryNew represents a folder in a module version, and the contents of that folder.
// DirectoryNew represents a directory in a module version, and the contents of that directory.
// It will replace LegacyDirectory once everything has been migrated.
type DirectoryNew struct {
DirectoryMeta
@ -128,6 +127,28 @@ type DirectoryNew struct {
Package *PackageNew
}
// PackageMeta represents the metadata of a package in a module version.
type PackageMeta struct {
DirectoryMeta
Name string
Synopsis string
}
// PackageMetaFromLegacyPackage returns a PackageMeta based on data from a
// LegacyPackage.
func PackageMetaFromLegacyPackage(pkg *LegacyPackage) *PackageMeta {
return &PackageMeta{
DirectoryMeta: DirectoryMeta{
Path: pkg.Path,
V1Path: pkg.V1Path,
Licenses: pkg.Licenses,
IsRedistributable: pkg.IsRedistributable,
},
Name: pkg.Name,
Synopsis: pkg.Synopsis,
}
}
// PackageNew is a group of one or more Go source files with the same package
// header. A PackageNew is part of a directory.
// It will replace LegacyPackage once everything has been migrated.
@ -273,8 +294,8 @@ const (
WithDocumentationHTML
)
// LegacyDirectory represents a folder in a module version, and all of the
// packages inside that folder.
// LegacyDirectory represents a directory in a module version, and all of the
// packages inside that directory.
type LegacyDirectory struct {
LegacyModuleInfo
Path string

Просмотреть файл

@ -132,16 +132,14 @@ func legacyCreateDirectory(dbDir *internal.LegacyDirectory, licmetas []*licenses
if !includeDirPath && pkg.Path == dbDir.Path {
continue
}
newPkg, err := legacyCreatePackage(pkg, &dbDir.ModuleInfo, false)
pm := internal.PackageMetaFromLegacyPackage(pkg)
newPkg, err := createPackage(pm, &dbDir.ModuleInfo, false)
if err != nil {
return nil, err
}
if pkg.IsRedistributable {
newPkg.Synopsis = pkg.Synopsis
}
newPkg.PathAfterDirectory = strings.TrimPrefix(strings.TrimPrefix(pkg.Path, dbDir.Path), "/")
newPkg.PathAfterDirectory = strings.TrimPrefix(strings.TrimPrefix(pm.Path, dbDir.Path), "/")
if newPkg.PathAfterDirectory == "" {
newPkg.PathAfterDirectory = effectiveName(pkg) + " (root)"
newPkg.PathAfterDirectory = effectiveName(pm.Path, pm.Name) + " (root)"
}
packages = append(packages, newPkg)
}

Просмотреть файл

@ -34,13 +34,19 @@ func TestFetchDirectoryDetails(t *testing.T) {
var wantPkgs []*Package
for _, suffix := range suffixes {
sp := sample.LegacyPackage(modulePath, suffix)
pkg, err := legacyCreatePackage(sp, mi, false)
pm := internal.PackageMetaFromLegacyPackage(sp)
pkg, err := createPackage(pm, mi, false)
if err != nil {
t.Fatal(err)
}
pkg.PathAfterDirectory = strings.TrimPrefix(strings.TrimPrefix(pm.Path, dirPath), "/")
if pkg.PathAfterDirectory == "" {
pkg.PathAfterDirectory = effectiveName(pm.Path, pm.Name) + " (root)"
}
pkg.Synopsis = sp.Synopsis
pkg.PathAfterDirectory = strings.TrimPrefix(strings.TrimPrefix(sp.Path, dirPath), "/")
if pkg.PathAfterDirectory == "" {
pkg.PathAfterDirectory = fmt.Sprintf("%s (root)", effectiveName(sp))
pkg.PathAfterDirectory = fmt.Sprintf("%s (root)", effectiveName(sp.Path, sp.Name))
}
wantPkgs = append(wantPkgs, pkg)
}

Просмотреть файл

@ -22,12 +22,12 @@ import (
type Package struct {
Module
Path string // full import path
PathAfterDirectory string // for display only; used only for directory
Synopsis string
IsRedistributable bool
URL string // relative to this site
LatestURL string // link with latest-version placeholder, relative to this site
IsRedistributable bool
Licenses []LicenseMetadata
PathAfterDirectory string // for display on the directories tab; used by Directory
Synopsis string // for display on the directories tab; used by Directory
}
// Module contains information for an individual module.
@ -42,18 +42,14 @@ type Module struct {
Licenses []LicenseMetadata
}
// legacyCreatePackage returns a *Package based on the fields of the specified
// createPackage returns a *Package based on the fields of the specified
// internal package and version info.
//
// latestRequested indicates whether the user requested the latest
// version of the package. If so, the returned Package.URL will have the
// structure /<path> instead of /<path>@<version>.
func legacyCreatePackage(pkg *internal.LegacyPackage, mi *internal.ModuleInfo, latestRequested bool) (_ *Package, err error) {
defer derrors.Wrap(&err, "legacyCreatePackage(%v, %v)", pkg, mi)
if pkg == nil || mi == nil {
return nil, fmt.Errorf("package and version info must not be nil")
}
func createPackage(pkg *internal.PackageMeta, mi *internal.ModuleInfo, latestRequested bool) (_ *Package, err error) {
defer derrors.Wrap(&err, "createPackage(%v, %v, %t)", pkg, mi, latestRequested)
var modLicenses []*licenses.Metadata
for _, lm := range pkg.Licenses {
@ -69,48 +65,12 @@ func legacyCreatePackage(pkg *internal.LegacyPackage, mi *internal.ModuleInfo, l
}
return &Package{
Path: pkg.Path,
Synopsis: pkg.Synopsis,
IsRedistributable: pkg.IsRedistributable,
Licenses: transformLicenseMetadata(pkg.Licenses),
Module: *m,
URL: constructPackageURL(pkg.Path, mi.ModulePath, urlVersion),
LatestURL: constructPackageURL(pkg.Path, mi.ModulePath, middleware.LatestVersionPlaceholder),
}, nil
}
// createPackageNew returns a *Package based on the fields of the specified
// internal package and version info.
//
// latestRequested indicates whether the user requested the latest
// version of the package. If so, the returned Package.URL will have the
// structure /<path> instead of /<path>@<version>.
func createPackageNew(vdir *internal.VersionedDirectory, latestRequested bool) (_ *Package, err error) {
defer derrors.Wrap(&err, "createPackageNew(%v, %t)", vdir, latestRequested)
if vdir == nil || vdir.Package == nil {
return nil, fmt.Errorf("package info must not be nil")
}
var modLicenses []*licenses.Metadata
for _, lm := range vdir.Licenses {
if path.Dir(lm.FilePath) == "." {
modLicenses = append(modLicenses, lm)
}
}
m := createModule(&vdir.ModuleInfo, modLicenses, latestRequested)
urlVersion := m.LinkVersion
if latestRequested {
urlVersion = internal.LatestVersion
}
return &Package{
Path: vdir.Path,
Synopsis: vdir.Package.Documentation.Synopsis,
IsRedistributable: vdir.DirectoryNew.IsRedistributable,
Licenses: transformLicenseMetadata(vdir.Licenses),
Module: *m,
URL: constructPackageURL(vdir.Path, vdir.ModulePath, urlVersion),
LatestURL: constructPackageURL(vdir.Path, vdir.ModulePath, middleware.LatestVersionPlaceholder),
Synopsis: pkg.Synopsis,
}, nil
}
@ -160,15 +120,15 @@ func constructPackageURL(pkgPath, modulePath, linkVersion string) string {
}
// effectiveName returns either the command name or package name.
func effectiveName(pkg *internal.LegacyPackage) string {
if pkg.Name != "main" {
return pkg.Name
func effectiveName(pkgPath, pkgName string) string {
if pkgName != "main" {
return pkgName
}
var prefix string // package path without version
if pkg.Path[len(pkg.Path)-3:] == "/v1" {
prefix = pkg.Path[:len(pkg.Path)-3]
if pkgPath[len(pkgPath)-3:] == "/v1" {
prefix = pkgPath[:len(pkgPath)-3]
} else {
prefix, _, _ = module.SplitPathVersion(pkg.Path)
prefix, _, _ = module.SplitPathVersion(pkgPath)
}
_, base := path.Split(prefix)
return base
@ -196,7 +156,7 @@ func packageHTMLTitle(pkg *internal.LegacyPackage) string {
if pkg.Name != "main" {
return pkg.Name + " package"
}
return effectiveName(pkg) + " command"
return effectiveName(pkg.Path, pkg.Name) + " command"
}
// packageHTMLTitleNew constructs the details page title for pkg.
@ -215,7 +175,7 @@ func packageTitle(pkg *internal.LegacyPackage) string {
if pkg.Name != "main" {
return "package " + pkg.Name
}
return "command " + effectiveName(pkg)
return "command " + effectiveName(pkg.Path, pkg.Name)
}
// packageTitleNew returns the package title as it will

Просмотреть файл

@ -19,9 +19,9 @@ import (
func samplePackage(mutators ...func(*Package)) *Package {
p := &Package{
Path: sample.PackagePath,
Synopsis: sample.Synopsis,
IsRedistributable: true,
Licenses: transformLicenseMetadata(sample.LicenseMetadata),
Synopsis: sample.Synopsis,
Module: Module{
DisplayVersion: sample.VersionString,
LinkVersion: sample.VersionString,
@ -91,7 +91,7 @@ func TestElapsedTime(t *testing.T) {
}
}
func TestCreatePackageHeader(t *testing.T) {
func TestCreatePackage(t *testing.T) {
vpkg := func(modulePath, suffix, name string) *internal.LegacyVersionedPackage {
vp := &internal.LegacyVersionedPackage{
LegacyModuleInfo: *sample.LegacyModuleInfo(modulePath, sample.VersionString),
@ -136,12 +136,13 @@ func TestCreatePackageHeader(t *testing.T) {
},
} {
t.Run(tc.label, func(t *testing.T) {
got, err := legacyCreatePackage(&tc.pkg.LegacyPackage, &tc.pkg.ModuleInfo, false)
pm := internal.PackageMetaFromLegacyPackage(&tc.pkg.LegacyPackage)
got, err := createPackage(pm, &tc.pkg.ModuleInfo, false)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(tc.wantPkg, got, cmp.AllowUnexported(safehtml.Identifier{})); diff != "" {
t.Errorf("legacyCreatePackage(%v) mismatch (-want +got):\n%s", tc.pkg, diff)
t.Errorf("createPackage(%v) mismatch (-want +got):\n%s", tc.pkg, diff)
}
})
}

Просмотреть файл

@ -88,7 +88,10 @@ func (s *Server) legacyServePackagePageWithPackage(ctx context.Context, w http.R
derrors.Wrap(&err, "legacyServePackagePageWithPackage(w, r, %q, %q, %q)", pkg.Path, pkg.ModulePath, requestedVersion)
}
}()
pkgHeader, err := legacyCreatePackage(&pkg.LegacyPackage, &pkg.ModuleInfo, requestedVersion == internal.LatestVersion)
pkgHeader, err := createPackage(
internal.PackageMetaFromLegacyPackage(&pkg.LegacyPackage),
&pkg.ModuleInfo,
requestedVersion == internal.LatestVersion)
if err != nil {
return fmt.Errorf("creating package header for %s@%s: %v", pkg.Path, pkg.Version, err)
}
@ -155,7 +158,15 @@ func (s *Server) stdlibPathForShortcut(ctx context.Context, shortcut string) (pa
func (s *Server) servePackagePageWithVersionedDirectory(ctx context.Context,
w http.ResponseWriter, r *http.Request, vdir *internal.VersionedDirectory, requestedVersion string) error {
pkgHeader, err := createPackageNew(vdir, requestedVersion == internal.LatestVersion)
pkgHeader, err := createPackage(&internal.PackageMeta{
DirectoryMeta: internal.DirectoryMeta{
Path: vdir.Path,
V1Path: vdir.V1Path,
Licenses: vdir.Licenses,
IsRedistributable: vdir.IsRedistributable,
},
Name: vdir.Package.Name,
Synopsis: vdir.Package.Documentation.Synopsis}, &vdir.ModuleInfo, requestedVersion == internal.LatestVersion)
if err != nil {
return fmt.Errorf("creating package header for %s@%s: %v", vdir.Path, vdir.Version, err)
}