internal/datasource: factor out GetUnit and GetUnitMeta
Move both methods into the shared datasource, and clean up the logic.
For golang/go#47780
Change-Id: I7ce0d29742652c63db2d2e55dedf6e378b838445
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/344950
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
diff --git a/internal/datasource/datasource.go b/internal/datasource/datasource.go
index c9a4888..25181ca 100644
--- a/internal/datasource/datasource.go
+++ b/internal/datasource/datasource.go
@@ -11,6 +11,7 @@
"context"
"errors"
"fmt"
+ "strings"
"time"
lru "github.com/hashicorp/golang-lru"
@@ -135,3 +136,68 @@
}
return nil, fmt.Errorf("%s@%s: %w", modulePath, version, derrors.NotFound)
}
+
+// findModule finds the module with longest module path containing the given
+// package path. It returns an error if no module is found.
+func (ds *dataSource) findModule(ctx context.Context, pkgPath, modulePath, version string) (_ *internal.Module, err error) {
+ defer derrors.Wrap(&err, "findModule(%q, %q, %q)", pkgPath, modulePath, version)
+
+ if modulePath != internal.UnknownModulePath {
+ return ds.getModule(ctx, modulePath, version)
+ }
+ pkgPath = strings.TrimLeft(pkgPath, "/")
+ for _, modulePath := range internal.CandidateModulePaths(pkgPath) {
+ m, err := ds.getModule(ctx, modulePath, version)
+ if err == nil {
+ return m, nil
+ }
+ if !errors.Is(err, derrors.NotFound) {
+ return nil, err
+ }
+ }
+ return nil, fmt.Errorf("could not find module for import path %s: %w", pkgPath, derrors.NotFound)
+}
+
+// GetUnitMeta returns information about a path.
+func (ds *dataSource) GetUnitMeta(ctx context.Context, path, requestedModulePath, requestedVersion string) (_ *internal.UnitMeta, err error) {
+ defer derrors.Wrap(&err, "GetUnitMeta(%q, %q, %q)", path, requestedModulePath, requestedVersion)
+
+ module, err := ds.findModule(ctx, path, requestedModulePath, requestedVersion)
+ if err != nil {
+ return nil, err
+ }
+ um := &internal.UnitMeta{
+ Path: path,
+ ModuleInfo: module.ModuleInfo,
+ }
+ if u := findUnit(module, path); u != nil {
+ um.Name = u.Name
+ um.IsRedistributable = u.IsRedistributable
+ }
+ return um, nil
+}
+
+// GetUnit returns information about a unit. Both the module path and package
+// path must be known.
+func (ds *dataSource) GetUnit(ctx context.Context, um *internal.UnitMeta, fields internal.FieldSet, bc internal.BuildContext) (_ *internal.Unit, err error) {
+ defer derrors.Wrap(&err, "GetUnit(%q, %q)", um.Path, um.ModulePath)
+
+ m, err := ds.getModule(ctx, um.ModulePath, um.Version)
+ if err != nil {
+ return nil, err
+ }
+ if u := findUnit(m, um.Path); u != nil {
+ return u, nil
+ }
+ return nil, fmt.Errorf("import path %s not found in module %s: %w", um.Path, um.ModulePath, derrors.NotFound)
+}
+
+// findUnit returns the unit with the given path in m, or nil if none.
+func findUnit(m *internal.Module, path string) *internal.Unit {
+ for _, u := range m.Units {
+ if u.Path == path {
+ return u
+ }
+ }
+ return nil
+}
diff --git a/internal/datasource/local.go b/internal/datasource/local.go
index 1b0a40e..2315d33 100644
--- a/internal/datasource/local.go
+++ b/internal/datasource/local.go
@@ -6,11 +6,9 @@
import (
"context"
- "errors"
"fmt"
"os"
"path/filepath"
- "strings"
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/derrors"
@@ -61,66 +59,14 @@
return ""
}
+func (ds *LocalDataSource) GetUnitMeta(ctx context.Context, path, requestedModulePath, requestedVersion string) (_ *internal.UnitMeta, err error) {
+ return ds.ds.GetUnitMeta(ctx, path, requestedModulePath, requestedVersion)
+}
+
// GetUnit returns information about a unit. Both the module path and package
// path must be known.
func (ds *LocalDataSource) GetUnit(ctx context.Context, pathInfo *internal.UnitMeta, fields internal.FieldSet, bc internal.BuildContext) (_ *internal.Unit, err error) {
- defer derrors.Wrap(&err, "GetUnit(%q, %q)", pathInfo.Path, pathInfo.ModulePath)
-
- module, err := ds.ds.getModule(ctx, pathInfo.ModulePath, pathInfo.Version)
- if err != nil {
- return nil, err
- }
- for _, unit := range module.Units {
- if unit.Path == pathInfo.Path {
- return unit, nil
- }
- }
-
- return nil, fmt.Errorf("import path %s not found in module %s: %w", pathInfo.Path, pathInfo.ModulePath, derrors.NotFound)
-}
-
-// GetUnitMeta returns information about a path.
-func (ds *LocalDataSource) GetUnitMeta(ctx context.Context, path, requestedModulePath, requestedVersion string) (_ *internal.UnitMeta, err error) {
- defer derrors.Wrap(&err, "GetUnitMeta(%q, %q, %q)", path, requestedModulePath, requestedVersion)
-
- module, err := ds.findModule(ctx, path, requestedModulePath, requestedVersion)
- if err != nil {
- return nil, err
- }
- um := &internal.UnitMeta{
- Path: path,
- ModuleInfo: module.ModuleInfo,
- }
-
- for _, u := range module.Units {
- if u.Path == path {
- um.Name = u.Name
- um.IsRedistributable = u.IsRedistributable
- }
- }
-
- return um, nil
-}
-
-// findModule finds the module with longest module path containing the given
-// package path. It returns an error if no module is found.
-func (ds *LocalDataSource) findModule(ctx context.Context, pkgPath, modulePath, version string) (_ *internal.Module, err error) {
- defer derrors.Wrap(&err, "findModule(%q, %q, %q)", pkgPath, modulePath, version)
-
- if modulePath != internal.UnknownModulePath {
- return ds.ds.getModule(ctx, modulePath, version)
- }
- pkgPath = strings.TrimLeft(pkgPath, "/")
- for _, modulePath := range internal.CandidateModulePaths(pkgPath) {
- m, err := ds.ds.getModule(ctx, modulePath, version)
- if err == nil {
- return m, nil
- }
- if !errors.Is(err, derrors.NotFound) {
- return nil, err
- }
- }
- return nil, fmt.Errorf("could not find module for import path %s: %w", pkgPath, derrors.NotFound)
+ return ds.ds.GetUnit(ctx, pathInfo, fields, bc)
}
// GetLatestInfo is not implemented.
diff --git a/internal/datasource/proxy.go b/internal/datasource/proxy.go
index 5e34ccf..f3d08dc 100644
--- a/internal/datasource/proxy.go
+++ b/internal/datasource/proxy.go
@@ -52,41 +52,6 @@
ds *dataSource
}
-// findModule finds the longest module path containing the given package path,
-// using the given finder func and iteratively testing parent directories of
-// the import path. It performs no testing as to whether the specified module
-// version that was found actually contains a package corresponding to pkgPath.
-func (ds *ProxyDataSource) findModule(ctx context.Context, pkgPath string, version string) (_ string, _ *proxy.VersionInfo, err error) {
- defer derrors.Wrap(&err, "findModule(%q, ...)", pkgPath)
- pkgPath = strings.TrimLeft(pkgPath, "/")
- for _, modulePath := range internal.CandidateModulePaths(pkgPath) {
- info, err := ds.ds.prox.Info(ctx, modulePath, version)
- if errors.Is(err, derrors.NotFound) {
- continue
- }
- if err != nil {
- return "", nil, err
- }
- return modulePath, info, nil
- }
- return "", nil, fmt.Errorf("unable to find module: %w", derrors.NotFound)
-}
-
-// getUnit returns information about a unit.
-func (ds *ProxyDataSource) getUnit(ctx context.Context, fullPath, modulePath, version string, _ internal.BuildContext) (_ *internal.Unit, err error) {
- var m *internal.Module
- m, err = ds.ds.getModule(ctx, modulePath, version)
- if err != nil {
- return nil, err
- }
- for _, d := range m.Units {
- if d.Path == fullPath {
- return d, nil
- }
- }
- return nil, fmt.Errorf("%q missing from module %s: %w", fullPath, m.ModulePath, derrors.NotFound)
-}
-
// GetLatestInfo returns latest information for unitPath and modulePath.
func (ds *ProxyDataSource) GetLatestInfo(ctx context.Context, unitPath, modulePath string, latestUnitMeta *internal.UnitMeta) (latest internal.LatestInfo, err error) {
defer derrors.Wrap(&err, "GetLatestInfo(ctx, %q, %q)", unitPath, modulePath)
diff --git a/internal/datasource/proxy_details.go b/internal/datasource/proxy_details.go
index d528562..3d01727 100644
--- a/internal/datasource/proxy_details.go
+++ b/internal/datasource/proxy_details.go
@@ -9,13 +9,12 @@
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/derrors"
- "golang.org/x/pkgsite/internal/proxy"
)
// GetUnit returns information about a directory at a path.
func (ds *ProxyDataSource) GetUnit(ctx context.Context, um *internal.UnitMeta, field internal.FieldSet, bc internal.BuildContext) (_ *internal.Unit, err error) {
defer derrors.Wrap(&err, "GetUnit(%q, %q, %q)", um.Path, um.ModulePath, um.Version)
- return ds.getUnit(ctx, um.Path, um.ModulePath, um.Version, bc)
+ return ds.ds.GetUnit(ctx, um, field, bc)
}
// GetModuleInfo returns the ModuleInfo as fetched from the proxy for module
@@ -29,38 +28,8 @@
return &m.ModuleInfo, nil
}
-// GetUnitMeta returns information about the given path.
-func (ds *ProxyDataSource) GetUnitMeta(ctx context.Context, path, inModulePath, inVersion string) (_ *internal.UnitMeta, err error) {
- defer derrors.Wrap(&err, "GetUnitMeta(%q, %q, %q)", path, inModulePath, inVersion)
-
- var info *proxy.VersionInfo
- if inModulePath == internal.UnknownModulePath {
- inModulePath, info, err = ds.findModule(ctx, path, inVersion)
- if err != nil {
- return nil, err
- }
- inVersion = info.Version
- }
- m, err := ds.ds.getModule(ctx, inModulePath, inVersion)
- if err != nil {
- return nil, err
- }
- um := &internal.UnitMeta{
- Path: path,
- ModuleInfo: internal.ModuleInfo{
- ModulePath: inModulePath,
- Version: inVersion,
- IsRedistributable: m.IsRedistributable,
- },
- }
- for _, d := range m.Units {
- if d.Path == path {
- um.Name = d.Name
- um.IsRedistributable = d.IsRedistributable
- break
- }
- }
- return um, nil
+func (ds *ProxyDataSource) GetUnitMeta(ctx context.Context, path, requestedModulePath, requestedVersion string) (_ *internal.UnitMeta, err error) {
+ return ds.ds.GetUnitMeta(ctx, path, requestedModulePath, requestedVersion)
}
// GetExperiments is unimplemented.
diff --git a/internal/datasource/proxy_test.go b/internal/datasource/proxy_test.go
index fcf7a6d..4fcd767 100644
--- a/internal/datasource/proxy_test.go
+++ b/internal/datasource/proxy_test.go
@@ -128,6 +128,14 @@
ctx, ds, teardown := setup(t, false)
defer teardown()
+ singleModInfo := internal.ModuleInfo{
+ ModulePath: "example.com/single",
+ Version: "v1.0.0",
+ IsRedistributable: true,
+ CommitTime: proxytest.CommitTime,
+ HasGoMod: true,
+ }
+
for _, test := range []struct {
path, modulePath, version string
want *internal.UnitMeta
@@ -137,11 +145,7 @@
modulePath: "example.com/single",
version: "v1.0.0",
want: &internal.UnitMeta{
- ModuleInfo: internal.ModuleInfo{
- ModulePath: "example.com/single",
- Version: "v1.0.0",
- IsRedistributable: true,
- },
+ ModuleInfo: singleModInfo,
IsRedistributable: true,
},
},
@@ -150,11 +154,7 @@
modulePath: "example.com/single",
version: "v1.0.0",
want: &internal.UnitMeta{
- ModuleInfo: internal.ModuleInfo{
- ModulePath: "example.com/single",
- Version: "v1.0.0",
- IsRedistributable: true,
- },
+ ModuleInfo: singleModInfo,
Name: "pkg",
IsRedistributable: true,
},
@@ -164,11 +164,7 @@
modulePath: internal.UnknownModulePath,
version: "v1.0.0",
want: &internal.UnitMeta{
- ModuleInfo: internal.ModuleInfo{
- ModulePath: "example.com/single",
- Version: "v1.0.0",
- IsRedistributable: true,
- },
+ ModuleInfo: singleModInfo,
Name: "pkg",
IsRedistributable: true,
},
@@ -182,6 +178,8 @@
ModulePath: "example.com/basic",
Version: "v1.1.0",
IsRedistributable: true,
+ CommitTime: proxytest.CommitTime,
+ HasGoMod: true,
},
Name: "basic",
IsRedistributable: true,
@@ -194,7 +192,7 @@
t.Fatal(err)
}
test.want.Path = test.path
- if diff := cmp.Diff(got, test.want); diff != "" {
+ if diff := cmp.Diff(test.want, got, cmpopts.IgnoreFields(internal.ModuleInfo{}, "SourceInfo")); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
diff --git a/internal/proxy/proxytest/server.go b/internal/proxy/proxytest/server.go
index 7b020fc..86fcbb5 100644
--- a/internal/proxy/proxytest/server.go
+++ b/internal/proxy/proxytest/server.go
@@ -167,7 +167,8 @@
return s.zipRequests
}
-const versionTime = "2019-01-30T00:00:00Z"
+// CommitTime is the time returned by all calls to the .info endpoint.
+var CommitTime = time.Date(2019, time.January, 30, 0, 0, 0, 0, time.UTC)
func cleanModule(m *Module) *Module {
if m.Version == "" {
@@ -188,5 +189,6 @@
}
func defaultInfo(resolvedVersion string) *strings.Reader {
- return strings.NewReader(fmt.Sprintf("{\n\t\"Version\": %q,\n\t\"Time\": %q\n}", resolvedVersion, versionTime))
+ return strings.NewReader(fmt.Sprintf("{\n\t\"Version\": %q,\n\t\"Time\": %q\n}",
+ resolvedVersion, CommitTime.Format(time.RFC3339)))
}