cmd/go/internal/modfetch: cache latest revinfo in Versions func

The responses have been cached by the web2 package before removed
it in CL 170879. This change add latest revinfo cache in Versions
func.

Fixes #51391

Change-Id: I73597e0a6b4938238e69d85e1cbbaa9007776db3
Reviewed-on: https://go-review.googlesource.com/c/go/+/403335
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Run-TryBot: Lee Baokun <bk@golangcn.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Baokun Lee 2022-05-01 14:32:02 +08:00 committed by Gopher Robot
parent d5bf9604aa
commit 7df0a002e6

View file

@ -187,6 +187,10 @@ type proxyRepo struct {
url *url.URL url *url.URL
path string path string
redactedURL string redactedURL string
listLatestOnce sync.Once
listLatest *RevInfo
listLatestErr error
} }
func newProxyRepo(baseURL, path string) (Repo, error) { func newProxyRepo(baseURL, path string) (Repo, error) {
@ -214,7 +218,7 @@ func newProxyRepo(baseURL, path string) (Repo, error) {
redactedURL := base.Redacted() redactedURL := base.Redacted()
base.Path = strings.TrimSuffix(base.Path, "/") + "/" + enc base.Path = strings.TrimSuffix(base.Path, "/") + "/" + enc
base.RawPath = strings.TrimSuffix(base.RawPath, "/") + "/" + pathEscape(enc) base.RawPath = strings.TrimSuffix(base.RawPath, "/") + "/" + pathEscape(enc)
return &proxyRepo{base, path, redactedURL}, nil return &proxyRepo{base, path, redactedURL, sync.Once{}, nil, nil}, nil
} }
func (p *proxyRepo) ModulePath() string { func (p *proxyRepo) ModulePath() string {
@ -278,32 +282,46 @@ func (p *proxyRepo) getBody(path string) (r io.ReadCloser, err error) {
func (p *proxyRepo) Versions(prefix string) ([]string, error) { func (p *proxyRepo) Versions(prefix string) ([]string, error) {
data, err := p.getBytes("@v/list") data, err := p.getBytes("@v/list")
if err != nil { if err != nil {
p.listLatestOnce.Do(func() {
p.listLatest, p.listLatestErr = nil, p.versionError("", err)
})
return nil, p.versionError("", err) return nil, p.versionError("", err)
} }
var list []string var list []string
for _, line := range strings.Split(string(data), "\n") { allLine := strings.Split(string(data), "\n")
for _, line := range allLine {
f := strings.Fields(line) f := strings.Fields(line)
if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !module.IsPseudoVersion(f[0]) { if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !module.IsPseudoVersion(f[0]) {
list = append(list, f[0]) list = append(list, f[0])
} }
} }
p.listLatestOnce.Do(func() {
p.listLatest, p.listLatestErr = p.latestFromList(allLine)
})
semver.Sort(list) semver.Sort(list)
return list, nil return list, nil
} }
func (p *proxyRepo) latest() (*RevInfo, error) { func (p *proxyRepo) latest() (*RevInfo, error) {
p.listLatestOnce.Do(func() {
data, err := p.getBytes("@v/list") data, err := p.getBytes("@v/list")
if err != nil { if err != nil {
return nil, p.versionError("", err) p.listLatestErr = p.versionError("", err)
return
}
list := strings.Split(string(data), "\n")
p.listLatest, p.listLatestErr = p.latestFromList(list)
})
return p.listLatest, p.listLatestErr
} }
func (p *proxyRepo) latestFromList(allLine []string) (*RevInfo, error) {
var ( var (
bestTime time.Time bestTime time.Time
bestTimeIsFromPseudo bool bestTimeIsFromPseudo bool
bestVersion string bestVersion string
) )
for _, line := range allLine {
for _, line := range strings.Split(string(data), "\n") {
f := strings.Fields(line) f := strings.Fields(line)
if len(f) >= 1 && semver.IsValid(f[0]) { if len(f) >= 1 && semver.IsValid(f[0]) {
// If the proxy includes timestamps, prefer the timestamp it reports. // If the proxy includes timestamps, prefer the timestamp it reports.