aboutsummaryrefslogtreecommitdiff
path: root/internal/stdlib/stdlib.go
diff options
context:
space:
mode:
authorJonathan Amsterdam <jba@google.com>2022-01-12 12:27:39 -0500
committerJonathan Amsterdam <jba@google.com>2022-01-13 12:13:38 +0000
commitde2b3089947146212b9ca3735befb3e2c93df6e7 (patch)
tree937838ae32c67339e2601223d87033c0ca471c19 /internal/stdlib/stdlib.go
parent5e4fb81f1c5c43697f71e4e7850925f852441b1d (diff)
downloadgo-x-pkgsite-de2b3089947146212b9ca3735befb3e2c93df6e7.tar.xz
internal/stdlib: refactor go repo logic
Add a goRepo interface, implemented for remote, local and test repos. Functions of stdlib use a global instance that interface instead of if statements. Also, improve and rewrite some tests. For golang/go#50229 Change-Id: I73641813e6c7a6bb9667f44a672e37dce964b17a Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/378094 Trust: Jonathan Amsterdam <jba@google.com> Run-TryBot: Jonathan Amsterdam <jba@google.com> Reviewed-by: Jamal Carvalho <jamal@golang.org>
Diffstat (limited to 'internal/stdlib/stdlib.go')
-rw-r--r--internal/stdlib/stdlib.go201
1 files changed, 36 insertions, 165 deletions
diff --git a/internal/stdlib/stdlib.go b/internal/stdlib/stdlib.go
index 926c7b32..654773ab 100644
--- a/internal/stdlib/stdlib.go
+++ b/internal/stdlib/stdlib.go
@@ -16,7 +16,6 @@ import (
"io/fs"
"os"
"path"
- "path/filepath"
"regexp"
"strings"
"sync"
@@ -24,16 +23,12 @@ import (
"golang.org/x/mod/semver"
"golang.org/x/pkgsite/internal/derrors"
- "golang.org/x/pkgsite/internal/testing/testhelper"
"golang.org/x/pkgsite/internal/version"
- "github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5"
- "github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/object"
- "github.com/go-git/go-git/v5/storage/memory"
)
const (
@@ -189,10 +184,6 @@ const (
GitHubRepo = "github.com/golang/go"
)
-// UseTestData determines whether to really clone the Go repo, or use
-// stripped-down versions of the repo from the testdata directory.
-var UseTestData = false
-
// TestCommitTime is the time used for all commits when UseTestData is true.
var (
TestCommitTime = time.Date(2019, 9, 4, 1, 2, 3, 0, time.UTC)
@@ -201,70 +192,47 @@ var (
)
var (
- goRepoPathMu sync.Mutex
- goRepoPath string
+ goRepoMu sync.Mutex
+ theGoRepo goRepo = &remoteGoRepo{}
)
-// SetGoRepoPath tells this package to obtain the Go repo from the
-// local filesystem at path, instead of cloning it.
-func SetGoRepoPath(path string) {
- goRepoPathMu.Lock()
- defer goRepoPathMu.Unlock()
- goRepoPath = path
-
+func getGoRepo() goRepo {
+ goRepoMu.Lock()
+ defer goRepoMu.Unlock()
+ return theGoRepo
}
-func getGoRepoPath() string {
- goRepoPathMu.Lock()
- defer goRepoPathMu.Unlock()
- return goRepoPath
+func swapGoRepo(gr goRepo) goRepo {
+ goRepoMu.Lock()
+ defer goRepoMu.Unlock()
+ old := theGoRepo
+ theGoRepo = gr
+ return old
}
-// getGoRepo returns a repo object for the Go repo at version.
-func getGoRepo(version string) (_ *git.Repository, _ plumbing.ReferenceName, err error) {
- defer derrors.Wrap(&err, "getGoRepo(%q)", version)
- if UseTestData {
- return getTestGoRepo(version)
- }
- if path := getGoRepoPath(); path != "" {
- return openGoRepo(path, version)
- }
- return cloneGoRepo(version)
+// WithTestData arranges for this package to use a testing version of the Go repo.
+// The returned function restores the previous state. Use with defer:
+// defer WithTestData()()
+func WithTestData() func() {
+ return withGoRepo(&testGoRepo{})
}
-// cloneGoRepo returns a repo object for the Go repo at version by cloning the
-// Go repo.
-func cloneGoRepo(v string) (_ *git.Repository, ref plumbing.ReferenceName, err error) {
- defer derrors.Wrap(&err, "cloneGoRepo(%q)", v)
-
- ref, err = refNameForVersion(v)
- if err != nil {
- return nil, "", err
- }
- repo, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
- URL: GoRepoURL,
- ReferenceName: ref,
- SingleBranch: true,
- Depth: 1,
- Tags: git.NoTags,
- })
- if err != nil {
- return nil, "", err
+func withGoRepo(gr goRepo) func() {
+ old := swapGoRepo(gr)
+ return func() {
+ swapGoRepo(old)
}
- return repo, ref, nil
}
-func openGoRepo(path, v string) (_ *git.Repository, _ plumbing.ReferenceName, err error) {
- defer derrors.Wrap(&err, "openGoRepo(%q)", v)
- repo, err := git.PlainOpen(path)
- if err != nil {
- return nil, "", err
- }
- ref, err := refNameForVersion(v)
+// SetGoRepoPath tells this package to obtain the Go repo from the
+// local filesystem at path, instead of cloning it.
+func SetGoRepoPath(path string) error {
+ gr, err := newLocalGoRepo(path)
if err != nil {
- return nil, "", err
+ return err
}
- return repo, ref, nil
+ swapGoRepo(gr)
+ return nil
}
func refNameForVersion(v string) (plumbing.ReferenceName, error) {
@@ -281,39 +249,6 @@ func refNameForVersion(v string) (plumbing.ReferenceName, error) {
return plumbing.NewTagReferenceName(tag), nil
}
-// getTestGoRepo gets a Go repo for testing.
-func getTestGoRepo(v string) (_ *git.Repository, _ plumbing.ReferenceName, err error) {
- defer derrors.Wrap(&err, "getTestGoRepo(%q)", v)
- if v == TestMasterVersion {
- v = version.Master
- }
- if v == TestDevFuzzVersion {
- v = DevFuzz
- }
- fs := osfs.New(filepath.Join(testhelper.TestDataPath("testdata"), v))
- repo, err := git.Init(memory.NewStorage(), fs)
- if err != nil {
- return nil, "", fmt.Errorf("git.Initi: %v", err)
- }
- wt, err := repo.Worktree()
- if err != nil {
- return nil, "", fmt.Errorf("repo.Worktree: %v", err)
- }
- // Add all files in the directory.
- if _, err := wt.Add(""); err != nil {
- return nil, "", fmt.Errorf("wt.Add(): %v", err)
- }
- _, err = wt.Commit("", &git.CommitOptions{All: true, Author: &object.Signature{
- Name: "Joe Random",
- Email: "joe@example.com",
- When: TestCommitTime,
- }})
- if err != nil {
- return nil, "", fmt.Errorf("wt.Commit: %v", err)
- }
- return repo, plumbing.HEAD, nil
-}
-
// Versions returns all the versions of Go that are relevant to the discovery
// site. These are all release versions (tags of the forms "goN.N" and
// "goN.N.N", where N is a number) and beta or rc versions (tags of the forms
@@ -321,39 +256,13 @@ func getTestGoRepo(v string) (_ *git.Repository, _ plumbing.ReferenceName, err e
func Versions() (_ []string, err error) {
defer derrors.Wrap(&err, "stdlib.Versions()")
- var refNames []plumbing.ReferenceName
- if UseTestData {
- refNames = testRefs
- } else if path := getGoRepoPath(); path != "" {
- repo, err := git.PlainOpen(path)
- if err != nil {
- return nil, err
- }
- iter, err := repo.References()
- if err != nil {
- return nil, err
- }
- defer iter.Close()
- err = iter.ForEach(func(r *plumbing.Reference) error {
- refNames = append(refNames, r.Name())
- return nil
- })
- if err != nil {
- return nil, err
- }
- } else {
- refs, err := remoteRefs()
- if err != nil {
- return nil, err
- }
- for _, r := range refs {
- refNames = append(refNames, r.Name())
- }
+ refs, err := getGoRepo().refs()
+ if err != nil {
+ return nil, err
}
-
var versions []string
- for _, name := range refNames {
- v := VersionForTag(name.Short())
+ for _, r := range refs {
+ v := VersionForTag(r.Name().Short())
if v != "" {
versions = append(versions, v)
}
@@ -366,7 +275,7 @@ func Versions() (_ []string, err error) {
func ResolveSupportedBranches() (_ map[string]string, err error) {
defer derrors.Wrap(&err, "ResolveSupportedBranches")
- refs, err := remoteRefs()
+ refs, err := getGoRepo().refs()
if err != nil {
return nil, err
}
@@ -380,15 +289,6 @@ func ResolveSupportedBranches() (_ map[string]string, err error) {
return m, nil
}
-func remoteRefs() (_ []*plumbing.Reference, err error) {
- defer derrors.Wrap(&err, "remoteRefs")
-
- re := git.NewRemote(memory.NewStorage(), &config.RemoteConfig{
- URLs: []string{GoRepoURL},
- })
- return re.List(&git.ListOptions{})
-}
-
// Directory returns the directory of the standard library relative to the repo root.
func Directory(v string) string {
if semver.Compare(v, "v1.4.0-beta.1") >= 0 ||
@@ -415,13 +315,13 @@ func ZipInfo(requestedVersion string) (resolvedVersion string, err error) {
}
func zipInternal(requestedVersion string) (_ *zip.Reader, resolvedVersion string, commitTime time.Time, prefix string, err error) {
- if !UseTestData && requestedVersion == version.Latest {
+ if requestedVersion == version.Latest {
requestedVersion, err = semanticVersion(requestedVersion)
if err != nil {
return nil, "", time.Time{}, "", err
}
}
- repo, refName, err := getGoRepo(requestedVersion)
+ repo, refName, err := getGoRepo().repoAtVersion(requestedVersion)
if err != nil {
return nil, "", time.Time{}, "", err
}
@@ -652,32 +552,3 @@ func Contains(path string) bool {
}
return !strings.Contains(path, ".")
}
-
-// References used for Versions during testing.
-var testRefs = []plumbing.ReferenceName{
- // stdlib versions
- "refs/tags/go1.2.1",
- "refs/tags/go1.3.2",
- "refs/tags/go1.4.2",
- "refs/tags/go1.4.3",
- "refs/tags/go1.6",
- "refs/tags/go1.6.3",
- "refs/tags/go1.6beta1",
- "refs/tags/go1.8",
- "refs/tags/go1.8rc2",
- "refs/tags/go1.9rc1",
- "refs/tags/go1.11",
- "refs/tags/go1.12",
- "refs/tags/go1.12.1",
- "refs/tags/go1.12.5",
- "refs/tags/go1.12.9",
- "refs/tags/go1.13",
- "refs/tags/go1.13beta1",
- "refs/tags/go1.14.6",
- "refs/heads/dev.fuzz",
- "refs/heads/master",
- // other tags
- "refs/changes/56/93156/13",
- "refs/tags/release.r59",
- "refs/tags/weekly.2011-04-13",
-}