diff options
| author | Jonathan Amsterdam <jba@google.com> | 2022-01-12 12:27:39 -0500 |
|---|---|---|
| committer | Jonathan Amsterdam <jba@google.com> | 2022-01-13 12:13:38 +0000 |
| commit | de2b3089947146212b9ca3735befb3e2c93df6e7 (patch) | |
| tree | 937838ae32c67339e2601223d87033c0ca471c19 /internal/stdlib/stdlib.go | |
| parent | 5e4fb81f1c5c43697f71e4e7850925f852441b1d (diff) | |
| download | go-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.go | 201 |
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", -} |
