aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Conrod <jayconrod@google.com>2020-09-02 14:53:02 -0400
committerJay Conrod <jayconrod@google.com>2020-09-11 18:14:49 +0000
commit07c1788357cfe6a4ee5f6f6a54d4fe9f579fa844 (patch)
tree32448169077e500502b8f5d04ec94b815c79990e
parent86ee84c40e2770ff189b6a4d835849107d9c749a (diff)
downloadgo-07c1788357cfe6a4ee5f6f6a54d4fe9f579fa844.tar.gz
go-07c1788357cfe6a4ee5f6f6a54d4fe9f579fa844.zip
cmd/go: move repository resolution from internal/get to internal/vcs
This is a refactoring intended to break the dependency from internal/modfetch to internal/get. No change in functionality is intended. Change-Id: If51aba7139cc0b62ecc9ba454c055c99e8f36f0f Reviewed-on: https://go-review.googlesource.com/c/go/+/254364 Run-TryBot: Jay Conrod <jayconrod@google.com> Reviewed-by: Bryan C. Mills <bcmills@google.com> Reviewed-by: Michael Matloob <matloob@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/cmd/go/internal/get/get.go35
-rw-r--r--src/cmd/go/internal/modfetch/repo.go12
-rw-r--r--src/cmd/go/internal/str/str_test.go27
-rw-r--r--src/cmd/go/internal/vcs/discovery.go (renamed from src/cmd/go/internal/get/discovery.go)2
-rw-r--r--src/cmd/go/internal/vcs/discovery_test.go (renamed from src/cmd/go/internal/get/pkg_test.go)23
-rw-r--r--src/cmd/go/internal/vcs/vcs.go (renamed from src/cmd/go/internal/get/vcs.go)277
-rw-r--r--src/cmd/go/internal/vcs/vcs_test.go (renamed from src/cmd/go/internal/get/vcs_test.go)46
7 files changed, 217 insertions, 205 deletions
diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go
index 9e4825eb37..3f7a66384a 100644
--- a/src/cmd/go/internal/get/get.go
+++ b/src/cmd/go/internal/get/get.go
@@ -18,6 +18,7 @@ import (
"cmd/go/internal/load"
"cmd/go/internal/search"
"cmd/go/internal/str"
+ "cmd/go/internal/vcs"
"cmd/go/internal/web"
"cmd/go/internal/work"
@@ -406,7 +407,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
// to make the first copy of or update a copy of the given package.
func downloadPackage(p *load.Package) error {
var (
- vcs *vcsCmd
+ vcsCmd *vcs.Cmd
repo, rootPath string
err error
blindRepo bool // set if the repo has unusual configuration
@@ -435,16 +436,16 @@ func downloadPackage(p *load.Package) error {
if p.Internal.Build.SrcRoot != "" {
// Directory exists. Look for checkout along path to src.
- vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
+ vcsCmd, rootPath, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot)
if err != nil {
return err
}
repo = "<local>" // should be unused; make distinctive
// Double-check where it came from.
- if *getU && vcs.remoteRepo != nil {
+ if *getU && vcsCmd.RemoteRepo != nil {
dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
- remote, err := vcs.remoteRepo(vcs, dir)
+ remote, err := vcsCmd.RemoteRepo(vcsCmd, dir)
if err != nil {
// Proceed anyway. The package is present; we likely just don't understand
// the repo configuration (e.g. unusual remote protocol).
@@ -452,10 +453,10 @@ func downloadPackage(p *load.Package) error {
}
repo = remote
if !*getF && err == nil {
- if rr, err := RepoRootForImportPath(importPrefix, IgnoreMod, security); err == nil {
+ if rr, err := vcs.RepoRootForImportPath(importPrefix, vcs.IgnoreMod, security); err == nil {
repo := rr.Repo
- if rr.vcs.resolveRepo != nil {
- resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
+ if rr.VCS.ResolveRepo != nil {
+ resolved, err := rr.VCS.ResolveRepo(rr.VCS, dir, repo)
if err == nil {
repo = resolved
}
@@ -469,13 +470,13 @@ func downloadPackage(p *load.Package) error {
} else {
// Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository.
- rr, err := RepoRootForImportPath(importPrefix, IgnoreMod, security)
+ rr, err := vcs.RepoRootForImportPath(importPrefix, vcs.IgnoreMod, security)
if err != nil {
return err
}
- vcs, repo, rootPath = rr.vcs, rr.Repo, rr.Root
+ vcsCmd, repo, rootPath = rr.VCS, rr.Repo, rr.Root
}
- if !blindRepo && !vcs.isSecure(repo) && security != web.Insecure {
+ if !blindRepo && !vcsCmd.IsSecure(repo) && security != web.Insecure {
return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
}
@@ -498,7 +499,7 @@ func downloadPackage(p *load.Package) error {
}
root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
- if err := checkNestedVCS(vcs, root, p.Internal.Build.SrcRoot); err != nil {
+ if err := vcs.CheckNested(vcsCmd, root, p.Internal.Build.SrcRoot); err != nil {
return err
}
@@ -514,7 +515,7 @@ func downloadPackage(p *load.Package) error {
// Check that this is an appropriate place for the repo to be checked out.
// The target directory must either not exist or have a repo checked out already.
- meta := filepath.Join(root, "."+vcs.cmd)
+ meta := filepath.Join(root, "."+vcsCmd.Cmd)
if _, err := os.Stat(meta); err != nil {
// Metadata file or directory does not exist. Prepare to checkout new copy.
// Some version control tools require the target directory not to exist.
@@ -535,12 +536,12 @@ func downloadPackage(p *load.Package) error {
fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.Internal.Build.Root)
}
- if err = vcs.create(root, repo); err != nil {
+ if err = vcsCmd.Create(root, repo); err != nil {
return err
}
} else {
// Metadata directory does exist; download incremental updates.
- if err = vcs.download(root); err != nil {
+ if err = vcsCmd.Download(root); err != nil {
return err
}
}
@@ -549,12 +550,12 @@ func downloadPackage(p *load.Package) error {
// Do not show tag sync in -n; it's noise more than anything,
// and since we're not running commands, no tag will be found.
// But avoid printing nothing.
- fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
+ fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcsCmd.Cmd)
return nil
}
// Select and sync to appropriate version of the repository.
- tags, err := vcs.tags(root)
+ tags, err := vcsCmd.Tags(root)
if err != nil {
return err
}
@@ -562,7 +563,7 @@ func downloadPackage(p *load.Package) error {
if i := strings.Index(vers, " "); i >= 0 {
vers = vers[:i]
}
- if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil {
+ if err := vcsCmd.TagSync(root, selectTag(vers, tags)); err != nil {
return err
}
diff --git a/src/cmd/go/internal/modfetch/repo.go b/src/cmd/go/internal/modfetch/repo.go
index 34f805d58a..eed4dd4258 100644
--- a/src/cmd/go/internal/modfetch/repo.go
+++ b/src/cmd/go/internal/modfetch/repo.go
@@ -13,9 +13,9 @@ import (
"time"
"cmd/go/internal/cfg"
- "cmd/go/internal/get"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/par"
+ "cmd/go/internal/vcs"
web "cmd/go/internal/web"
"golang.org/x/mod/module"
@@ -261,13 +261,13 @@ func lookupDirect(path string) (Repo, error) {
if allowInsecure(path) {
security = web.Insecure
}
- rr, err := get.RepoRootForImportPath(path, get.PreferMod, security)
+ rr, err := vcs.RepoRootForImportPath(path, vcs.PreferMod, security)
if err != nil {
// We don't know where to find code for a module with this path.
return nil, notExistError{err: err}
}
- if rr.VCS == "mod" {
+ if rr.VCS.Name == "mod" {
// Fetch module from proxy with base URL rr.Repo.
return newProxyRepo(rr.Repo, path)
}
@@ -279,8 +279,8 @@ func lookupDirect(path string) (Repo, error) {
return newCodeRepo(code, rr.Root, path)
}
-func lookupCodeRepo(rr *get.RepoRoot) (codehost.Repo, error) {
- code, err := codehost.NewRepo(rr.VCS, rr.Repo)
+func lookupCodeRepo(rr *vcs.RepoRoot) (codehost.Repo, error) {
+ code, err := codehost.NewRepo(rr.VCS.Cmd, rr.Repo)
if err != nil {
if _, ok := err.(*codehost.VCSError); ok {
return nil, err
@@ -306,7 +306,7 @@ func ImportRepoRev(path, rev string) (Repo, *RevInfo, error) {
if allowInsecure(path) {
security = web.Insecure
}
- rr, err := get.RepoRootForImportPath(path, get.IgnoreMod, security)
+ rr, err := vcs.RepoRootForImportPath(path, vcs.IgnoreMod, security)
if err != nil {
return nil, nil, err
}
diff --git a/src/cmd/go/internal/str/str_test.go b/src/cmd/go/internal/str/str_test.go
new file mode 100644
index 0000000000..147ce1a63e
--- /dev/null
+++ b/src/cmd/go/internal/str/str_test.go
@@ -0,0 +1,27 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package str
+
+import "testing"
+
+var foldDupTests = []struct {
+ list []string
+ f1, f2 string
+}{
+ {StringList("math/rand", "math/big"), "", ""},
+ {StringList("math", "strings"), "", ""},
+ {StringList("strings"), "", ""},
+ {StringList("strings", "strings"), "strings", "strings"},
+ {StringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"},
+}
+
+func TestFoldDup(t *testing.T) {
+ for _, tt := range foldDupTests {
+ f1, f2 := FoldDup(tt.list)
+ if f1 != tt.f1 || f2 != tt.f2 {
+ t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2)
+ }
+ }
+}
diff --git a/src/cmd/go/internal/get/discovery.go b/src/cmd/go/internal/vcs/discovery.go
index afa6ef455f..327b44cb9a 100644
--- a/src/cmd/go/internal/get/discovery.go
+++ b/src/cmd/go/internal/vcs/discovery.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package get
+package vcs
import (
"encoding/xml"
diff --git a/src/cmd/go/internal/get/pkg_test.go b/src/cmd/go/internal/vcs/discovery_test.go
index fc6a179c2e..eb99fdf64c 100644
--- a/src/cmd/go/internal/get/pkg_test.go
+++ b/src/cmd/go/internal/vcs/discovery_test.go
@@ -2,35 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package get
+package vcs
import (
- "cmd/go/internal/str"
"reflect"
"strings"
"testing"
)
-var foldDupTests = []struct {
- list []string
- f1, f2 string
-}{
- {str.StringList("math/rand", "math/big"), "", ""},
- {str.StringList("math", "strings"), "", ""},
- {str.StringList("strings"), "", ""},
- {str.StringList("strings", "strings"), "strings", "strings"},
- {str.StringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"},
-}
-
-func TestFoldDup(t *testing.T) {
- for _, tt := range foldDupTests {
- f1, f2 := str.FoldDup(tt.list)
- if f1 != tt.f1 || f2 != tt.f2 {
- t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2)
- }
- }
-}
-
var parseMetaGoImportsTests = []struct {
in string
mod ModuleMode
diff --git a/src/cmd/go/internal/get/vcs.go b/src/cmd/go/internal/vcs/vcs.go
index 24c32935d0..e535998d89 100644
--- a/src/cmd/go/internal/get/vcs.go
+++ b/src/cmd/go/internal/vcs/vcs.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package get
+package vcs
import (
"encoding/json"
@@ -27,23 +27,23 @@ import (
// A vcsCmd describes how to use a version control system
// like Mercurial, Git, or Subversion.
-type vcsCmd struct {
- name string
- cmd string // name of binary to invoke command
+type Cmd struct {
+ Name string
+ Cmd string // name of binary to invoke command
- createCmd []string // commands to download a fresh copy of a repository
- downloadCmd []string // commands to download updates into an existing repository
+ CreateCmd []string // commands to download a fresh copy of a repository
+ DownloadCmd []string // commands to download updates into an existing repository
- tagCmd []tagCmd // commands to list tags
- tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd
- tagSyncCmd []string // commands to sync to specific tag
- tagSyncDefault []string // commands to sync to default tag
+ TagCmd []tagCmd // commands to list tags
+ TagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd
+ TagSyncCmd []string // commands to sync to specific tag
+ TagSyncDefault []string // commands to sync to default tag
- scheme []string
- pingCmd string
+ Scheme []string
+ PingCmd string
- remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)
- resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)
+ RemoteRepo func(v *Cmd, rootDir string) (remoteRepo string, err error)
+ ResolveRepo func(v *Cmd, rootDir, remoteRepo string) (realRepo string, err error)
}
var defaultSecureScheme = map[string]bool{
@@ -54,7 +54,7 @@ var defaultSecureScheme = map[string]bool{
"ssh": true,
}
-func (v *vcsCmd) isSecure(repo string) bool {
+func (v *Cmd) IsSecure(repo string) bool {
u, err := urlpkg.Parse(repo)
if err != nil {
// If repo is not a URL, it's not secure.
@@ -63,8 +63,8 @@ func (v *vcsCmd) isSecure(repo string) bool {
return v.isSecureScheme(u.Scheme)
}
-func (v *vcsCmd) isSecureScheme(scheme string) bool {
- switch v.cmd {
+func (v *Cmd) isSecureScheme(scheme string) bool {
+ switch v.Cmd {
case "git":
// GIT_ALLOW_PROTOCOL is an environment variable defined by Git. It is a
// colon-separated list of schemes that are allowed to be used with git
@@ -89,7 +89,7 @@ type tagCmd struct {
}
// vcsList lists the known version control systems
-var vcsList = []*vcsCmd{
+var vcsList = []*Cmd{
vcsHg,
vcsGit,
vcsSvn,
@@ -97,11 +97,15 @@ var vcsList = []*vcsCmd{
vcsFossil,
}
+// vcsMod is a stub for the "mod" scheme. It's returned by
+// repoRootForImportPathDynamic, but is otherwise not treated as a VCS command.
+var vcsMod = &Cmd{Name: "mod"}
+
// vcsByCmd returns the version control system for the given
// command name (hg, git, svn, bzr).
-func vcsByCmd(cmd string) *vcsCmd {
+func vcsByCmd(cmd string) *Cmd {
for _, vcs := range vcsList {
- if vcs.cmd == cmd {
+ if vcs.Cmd == cmd {
return vcs
}
}
@@ -109,31 +113,31 @@ func vcsByCmd(cmd string) *vcsCmd {
}
// vcsHg describes how to use Mercurial.
-var vcsHg = &vcsCmd{
- name: "Mercurial",
- cmd: "hg",
+var vcsHg = &Cmd{
+ Name: "Mercurial",
+ Cmd: "hg",
- createCmd: []string{"clone -U -- {repo} {dir}"},
- downloadCmd: []string{"pull"},
+ CreateCmd: []string{"clone -U -- {repo} {dir}"},
+ DownloadCmd: []string{"pull"},
// We allow both tag and branch names as 'tags'
// for selecting a version. This lets people have
// a go.release.r60 branch and a go1 branch
// and make changes in both, without constantly
// editing .hgtags.
- tagCmd: []tagCmd{
+ TagCmd: []tagCmd{
{"tags", `^(\S+)`},
{"branches", `^(\S+)`},
},
- tagSyncCmd: []string{"update -r {tag}"},
- tagSyncDefault: []string{"update default"},
+ TagSyncCmd: []string{"update -r {tag}"},
+ TagSyncDefault: []string{"update default"},
- scheme: []string{"https", "http", "ssh"},
- pingCmd: "identify -- {scheme}://{repo}",
- remoteRepo: hgRemoteRepo,
+ Scheme: []string{"https", "http", "ssh"},
+ PingCmd: "identify -- {scheme}://{repo}",
+ RemoteRepo: hgRemoteRepo,
}
-func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error) {
+func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) {
out, err := vcsHg.runOutput(rootDir, "paths default")
if err != nil {
return "", err
@@ -142,45 +146,45 @@ func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error)
}
// vcsGit describes how to use Git.
-var vcsGit = &vcsCmd{
- name: "Git",
- cmd: "git",
+var vcsGit = &Cmd{
+ Name: "Git",
+ Cmd: "git",
- createCmd: []string{"clone -- {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},
- downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
+ CreateCmd: []string{"clone -- {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},
+ DownloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
- tagCmd: []tagCmd{
+ TagCmd: []tagCmd{
// tags/xxx matches a git tag named xxx
// origin/xxx matches a git branch named xxx on the default remote repository
{"show-ref", `(?:tags|origin)/(\S+)$`},
},
- tagLookupCmd: []tagCmd{
+ TagLookupCmd: []tagCmd{
{"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
},
- tagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"},
+ TagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"},
// both createCmd and downloadCmd update the working dir.
// No need to do more here. We used to 'checkout master'
// but that doesn't work if the default branch is not named master.
// DO NOT add 'checkout master' here.
// See golang.org/issue/9032.
- tagSyncDefault: []string{"submodule update --init --recursive"},
+ TagSyncDefault: []string{"submodule update --init --recursive"},
- scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
+ Scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
// Leave out the '--' separator in the ls-remote command: git 2.7.4 does not
// support such a separator for that command, and this use should be safe
// without it because the {scheme} value comes from the predefined list above.
// See golang.org/issue/33836.
- pingCmd: "ls-remote {scheme}://{repo}",
+ PingCmd: "ls-remote {scheme}://{repo}",
- remoteRepo: gitRemoteRepo,
+ RemoteRepo: gitRemoteRepo,
}
// scpSyntaxRe matches the SCP-like addresses used by Git to access
// repositories by SSH.
var scpSyntaxRe = lazyregexp.New(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
-func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) {
+func gitRemoteRepo(vcsGit *Cmd, rootDir string) (remoteRepo string, err error) {
cmd := "config remote.origin.url"
errParse := errors.New("unable to parse output of git " + cmd)
errRemoteOriginNotFound := errors.New("remote origin not found")
@@ -216,7 +220,7 @@ func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error
// Iterate over insecure schemes too, because this function simply
// reports the state of the repo. If we can't see insecure schemes then
// we can't report the actual repo URL.
- for _, s := range vcsGit.scheme {
+ for _, s := range vcsGit.Scheme {
if repoURL.Scheme == s {
return repoURL.String(), nil
}
@@ -225,27 +229,27 @@ func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error
}
// vcsBzr describes how to use Bazaar.
-var vcsBzr = &vcsCmd{
- name: "Bazaar",
- cmd: "bzr",
+var vcsBzr = &Cmd{
+ Name: "Bazaar",
+ Cmd: "bzr",
- createCmd: []string{"branch -- {repo} {dir}"},
+ CreateCmd: []string{"branch -- {repo} {dir}"},
// Without --overwrite bzr will not pull tags that changed.
// Replace by --overwrite-tags after http://pad.lv/681792 goes in.
- downloadCmd: []string{"pull --overwrite"},
+ DownloadCmd: []string{"pull --overwrite"},
- tagCmd: []tagCmd{{"tags", `^(\S+)`}},
- tagSyncCmd: []string{"update -r {tag}"},
- tagSyncDefault: []string{"update -r revno:-1"},
+ TagCmd: []tagCmd{{"tags", `^(\S+)`}},
+ TagSyncCmd: []string{"update -r {tag}"},
+ TagSyncDefault: []string{"update -r revno:-1"},
- scheme: []string{"https", "http", "bzr", "bzr+ssh"},
- pingCmd: "info -- {scheme}://{repo}",
- remoteRepo: bzrRemoteRepo,
- resolveRepo: bzrResolveRepo,
+ Scheme: []string{"https", "http", "bzr", "bzr+ssh"},
+ PingCmd: "info -- {scheme}://{repo}",
+ RemoteRepo: bzrRemoteRepo,
+ ResolveRepo: bzrResolveRepo,
}
-func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) {
+func bzrRemoteRepo(vcsBzr *Cmd, rootDir string) (remoteRepo string, err error) {
outb, err := vcsBzr.runOutput(rootDir, "config parent_location")
if err != nil {
return "", err
@@ -253,7 +257,7 @@ func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error
return strings.TrimSpace(string(outb)), nil
}
-func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) {
+func bzrResolveRepo(vcsBzr *Cmd, rootDir, remoteRepo string) (realRepo string, err error) {
outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo)
if err != nil {
return "", err
@@ -287,22 +291,22 @@ func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string
}
// vcsSvn describes how to use Subversion.
-var vcsSvn = &vcsCmd{
- name: "Subversion",
- cmd: "svn",
+var vcsSvn = &Cmd{
+ Name: "Subversion",
+ Cmd: "svn",
- createCmd: []string{"checkout -- {repo} {dir}"},
- downloadCmd: []string{"update"},
+ CreateCmd: []string{"checkout -- {repo} {dir}"},
+ DownloadCmd: []string{"update"},
// There is no tag command in subversion.
// The branch information is all in the path names.
- scheme: []string{"https", "http", "svn", "svn+ssh"},
- pingCmd: "info -- {scheme}://{repo}",
- remoteRepo: svnRemoteRepo,
+ Scheme: []string{"https", "http", "svn", "svn+ssh"},
+ PingCmd: "info -- {scheme}://{repo}",
+ RemoteRepo: svnRemoteRepo,
}
-func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error) {
+func svnRemoteRepo(vcsSvn *Cmd, rootDir string) (remoteRepo string, err error) {
outb, err := vcsSvn.runOutput(rootDir, "info")
if err != nil {
return "", err
@@ -337,22 +341,22 @@ func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error
const fossilRepoName = ".fossil"
// vcsFossil describes how to use Fossil (fossil-scm.org)
-var vcsFossil = &vcsCmd{
- name: "Fossil",
- cmd: "fossil",
+var vcsFossil = &Cmd{
+ Name: "Fossil",
+ Cmd: "fossil",
- createCmd: []string{"-go-internal-mkdir {dir} clone -- {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"},
- downloadCmd: []string{"up"},
+ CreateCmd: []string{"-go-internal-mkdir {dir} clone -- {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"},
+ DownloadCmd: []string{"up"},
- tagCmd: []tagCmd{{"tag ls", `(.*)`}},
- tagSyncCmd: []string{"up tag:{tag}"},
- tagSyncDefault: []string{"up trunk"},
+ TagCmd: []tagCmd{{"tag ls", `(.*)`}},
+ TagSyncCmd: []string{"up tag:{tag}"},
+ TagSyncDefault: []string{"up trunk"},
- scheme: []string{"https", "http"},
- remoteRepo: fossilRemoteRepo,
+ Scheme: []string{"https", "http"},
+ RemoteRepo: fossilRemoteRepo,
}
-func fossilRemoteRepo(vcsFossil *vcsCmd, rootDir string) (remoteRepo string, err error) {
+func fossilRemoteRepo(vcsFossil *Cmd, rootDir string) (remoteRepo string, err error) {
out, err := vcsFossil.runOutput(rootDir, "remote-url")
if err != nil {
return "", err
@@ -360,8 +364,8 @@ func fossilRemoteRepo(vcsFossil *vcsCmd, rootDir string) (remoteRepo string, err
return strings.TrimSpace(string(out)), nil
}
-func (v *vcsCmd) String() string {
- return v.name
+func (v *Cmd) String() string {
+ return v.Name
}
// run runs the command line cmd in the given directory.
@@ -371,24 +375,24 @@ func (v *vcsCmd) String() string {
// If an error occurs, run prints the command line and the
// command's combined stdout+stderr to standard error.
// Otherwise run discards the command's output.
-func (v *vcsCmd) run(dir string, cmd string, keyval ...string) error {
+func (v *Cmd) run(dir string, cmd string, keyval ...string) error {
_, err := v.run1(dir, cmd, keyval, true)
return err
}
// runVerboseOnly is like run but only generates error output to standard error in verbose mode.
-func (v *vcsCmd) runVerboseOnly(dir string, cmd string, keyval ...string) error {
+func (v *Cmd) runVerboseOnly(dir string, cmd string, keyval ...string) error {
_, err := v.run1(dir, cmd, keyval, false)
return err
}
// runOutput is like run but returns the output of the command.
-func (v *vcsCmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) {
+func (v *Cmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) {
return v.run1(dir, cmd, keyval, true)
}
// run1 is the generalized implementation of run and runOutput.
-func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) {
+func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) {
m := make(map[string]string)
for i := 0; i < len(keyval); i += 2 {
m[keyval[i]] = keyval[i+1]
@@ -420,25 +424,25 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
args = args[2:]
}
- _, err := exec.LookPath(v.cmd)
+ _, err := exec.LookPath(v.Cmd)
if err != nil {
fmt.Fprintf(os.Stderr,
"go: missing %s command. See https://golang.org/s/gogetcmd\n",
- v.name)
+ v.Name)
return nil, err
}
- cmd := exec.Command(v.cmd, args...)
+ cmd := exec.Command(v.Cmd, args...)
cmd.Dir = dir
cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
if cfg.BuildX {
fmt.Fprintf(os.Stderr, "cd %s\n", dir)
- fmt.Fprintf(os.Stderr, "%s %s\n", v.cmd, strings.Join(args, " "))
+ fmt.Fprintf(os.Stderr, "%s %s\n", v.Cmd, strings.Join(args, " "))
}
out, err := cmd.Output()
if err != nil {
if verbose || cfg.BuildV {
- fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
+ fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.Cmd, strings.Join(args, " "))
if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
os.Stderr.Write(ee.Stderr)
} else {
@@ -449,15 +453,15 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
return out, err
}
-// ping pings to determine scheme to use.
-func (v *vcsCmd) ping(scheme, repo string) error {
- return v.runVerboseOnly(".", v.pingCmd, "scheme", scheme, "repo", repo)
+// Ping pings to determine scheme to use.
+func (v *Cmd) Ping(scheme, repo string) error {
+ return v.runVerboseOnly(".", v.PingCmd, "scheme", scheme, "repo", repo)
}
-// create creates a new copy of repo in dir.
+// Create creates a new copy of repo in dir.
// The parent of dir must exist; dir must not.
-func (v *vcsCmd) create(dir, repo string) error {
- for _, cmd := range v.createCmd {
+func (v *Cmd) Create(dir, repo string) error {
+ for _, cmd := range v.CreateCmd {
if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
return err
}
@@ -465,9 +469,9 @@ func (v *vcsCmd) create(dir, repo string) error {
return nil
}
-// download downloads any new changes for the repo in dir.
-func (v *vcsCmd) download(dir string) error {
- for _, cmd := range v.downloadCmd {
+// Download downloads any new changes for the repo in dir.
+func (v *Cmd) Download(dir string) error {
+ for _, cmd := range v.DownloadCmd {
if err := v.run(dir, cmd); err != nil {
return err
}
@@ -475,10 +479,10 @@ func (v *vcsCmd) download(dir string) error {
return nil
}
-// tags returns the list of available tags for the repo in dir.
-func (v *vcsCmd) tags(dir string) ([]string, error) {
+// Tags returns the list of available tags for the repo in dir.
+func (v *Cmd) Tags(dir string) ([]string, error) {
var tags []string
- for _, tc := range v.tagCmd {
+ for _, tc := range v.TagCmd {
out, err := v.runOutput(dir, tc.cmd)
if err != nil {
return nil, err
@@ -493,12 +497,12 @@ func (v *vcsCmd) tags(dir string) ([]string, error) {
// tagSync syncs the repo in dir to the named tag,
// which either is a tag returned by tags or is v.tagDefault.
-func (v *vcsCmd) tagSync(dir, tag string) error {
- if v.tagSyncCmd == nil {
+func (v *Cmd) TagSync(dir, tag string) error {
+ if v.TagSyncCmd == nil {
return nil
}
if tag != "" {
- for _, tc := range v.tagLookupCmd {
+ for _, tc := range v.TagLookupCmd {
out, err := v.runOutput(dir, tc.cmd, "tag", tag)
if err != nil {
return err
@@ -512,8 +516,8 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
}
}
- if tag == "" && v.tagSyncDefault != nil {
- for _, cmd := range v.tagSyncDefault {
+ if tag == "" && v.TagSyncDefault != nil {
+ for _, cmd := range v.TagSyncDefault {
if err := v.run(dir, cmd); err != nil {
return err
}
@@ -521,7 +525,7 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
return nil
}
- for _, cmd := range v.tagSyncCmd {
+ for _, cmd := range v.TagSyncCmd {
if err := v.run(dir, cmd, "tag", tag); err != nil {
return err
}
@@ -540,11 +544,11 @@ type vcsPath struct {
schemelessRepo bool // if true, the repo pattern lacks a scheme
}
-// vcsFromDir inspects dir and its parents to determine the
+// FromDir inspects dir and its parents to determine the
// version control system and code repository to use.
// On return, root is the import path
// corresponding to the root of the repository.
-func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
+func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) {
// Clean and double-check that dir is in (a subdirectory of) srcRoot.
dir = filepath.Clean(dir)
srcRoot = filepath.Clean(srcRoot)
@@ -552,13 +556,13 @@ func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
}
- var vcsRet *vcsCmd
+ var vcsRet *Cmd
var rootRet string
origDir := dir
for len(dir) > len(srcRoot) {
for _, vcs := range vcsList {
- if _, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil {
+ if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil {
root := filepath.ToSlash(dir[len(srcRoot)+1:])
// Record first VCS we find, but keep looking,
// to detect mistakes like one kind of VCS inside another.
@@ -568,12 +572,12 @@ func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
continue
}
// Allow .git inside .git, which can arise due to submodules.
- if vcsRet == vcs && vcs.cmd == "git" {
+ if vcsRet == vcs && vcs.Cmd == "git" {
continue
}
// Otherwise, we have one VCS inside a different VCS.
return nil, "", fmt.Errorf("directory %q uses %s, but parent %q uses %s",
- filepath.Join(srcRoot, rootRet), vcsRet.cmd, filepath.Join(srcRoot, root), vcs.cmd)
+ filepath.Join(srcRoot, rootRet), vcsRet.Cmd, filepath.Join(srcRoot, root), vcs.Cmd)
}
}
@@ -593,9 +597,9 @@ func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir)
}
-// checkNestedVCS checks for an incorrectly-nested VCS-inside-VCS
+// CheckNested checks for an incorrectly-nested VCS-inside-VCS
// situation for dir, checking parents up until srcRoot.
-func checkNestedVCS(vcs *vcsCmd, dir, srcRoot string) error {
+func CheckNested(vcs *Cmd, dir, srcRoot string) error {
if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
return fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
}
@@ -603,17 +607,17 @@ func checkNestedVCS(vcs *vcsCmd, dir, srcRoot string) error {
otherDir := dir
for len(otherDir) > len(srcRoot) {
for _, otherVCS := range vcsList {
- if _, err := os.Stat(filepath.Join(otherDir, "."+otherVCS.cmd)); err == nil {
+ if _, err := os.Stat(filepath.Join(otherDir, "."+otherVCS.Cmd)); err == nil {
// Allow expected vcs in original dir.
if otherDir == dir && otherVCS == vcs {
continue
}
// Allow .git inside .git, which can arise due to submodules.
- if otherVCS == vcs && vcs.cmd == "git" {
+ if otherVCS == vcs && vcs.Cmd == "git" {
continue
}
// Otherwise, we have one VCS inside a different VCS.
- return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.cmd, otherDir, otherVCS.cmd)
+ return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.Cmd, otherDir, otherVCS.Cmd)
}
}
// Move to parent.
@@ -633,9 +637,7 @@ type RepoRoot struct {
Repo string // repository URL, including scheme
Root string // import path corresponding to root of repo
IsCustom bool // defined by served <meta> tags (as opposed to hard-coded pattern)
- VCS string // vcs type ("mod", "git", ...)
-
- vcs *vcsCmd // internal: vcs command access
+ VCS *Cmd
}
func httpPrefix(s string) string {
@@ -735,15 +737,15 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
if !srv.schemelessRepo {
repoURL = match["repo"]
} else {
- scheme := vcs.scheme[0] // default to first scheme
+ scheme := vcs.Scheme[0] // default to first scheme
repo := match["repo"]
- if vcs.pingCmd != "" {
+ if vcs.PingCmd != "" {
// If we know how to test schemes, scan to find one.
- for _, s := range vcs.scheme {
+ for _, s := range vcs.Scheme {
if security == web.SecureOnly && !vcs.isSecureScheme(s) {
continue
}
- if vcs.ping(s, repo) == nil {
+ if vcs.Ping(s, repo) == nil {
scheme = s
break
}
@@ -754,8 +756,7 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
rr := &RepoRoot{
Repo: repoURL,
Root: match["root"],
- VCS: vcs.cmd,
- vcs: vcs,
+ VCS: vcs,
}
return rr, nil
}
@@ -846,17 +847,21 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
if err := validateRepoRoot(mmi.RepoRoot); err != nil {
return nil, fmt.Errorf("%s: invalid repo root %q: %v", resp.URL, mmi.RepoRoot, err)
}
- vcs := vcsByCmd(mmi.VCS)
- if vcs == nil && mmi.VCS != "mod" {
- return nil, fmt.Errorf("%s: unknown vcs %q", resp.URL, mmi.VCS)
+ var vcs *Cmd
+ if mmi.VCS == "mod" {
+ vcs = vcsMod
+ } else {
+ vcs = vcsByCmd(mmi.VCS)
+ if vcs == nil {
+ return nil, fmt.Errorf("%s: unknown vcs %q", resp.URL, mmi.VCS)
+ }
}
rr := &RepoRoot{
Repo: mmi.RepoRoot,
Root: mmi.Prefix,
IsCustom: true,
- VCS: mmi.VCS,
- vcs: vcs,
+ VCS: vcs,
}
return rr, nil
}
@@ -1103,7 +1108,7 @@ var vcsPathsAfterDynamic = []*vcsPath{
func noVCSSuffix(match map[string]string) error {
repo := match["repo"]
for _, vcs := range vcsList {
- if strings.HasSuffix(repo, "."+vcs.cmd) {
+ if strings.HasSuffix(repo, "."+vcs.Cmd) {
return fmt.Errorf("invalid version control suffix in %s path", match["prefix"])
}
}
@@ -1133,7 +1138,7 @@ func bitbucketVCS(match map[string]string) error {
// VCS it uses. See issue 5375.
root := match["root"]
for _, vcs := range []string{"git", "hg"} {
- if vcsByCmd(vcs).ping("https", root) == nil {
+ if vcsByCmd(vcs).Ping("https", root) == nil {
resp.SCM = vcs
break
}
diff --git a/src/cmd/go/internal/get/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go
index 195bc231eb..5b874204f1 100644
--- a/src/cmd/go/internal/get/vcs_test.go
+++ b/src/cmd/go/internal/vcs/vcs_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package get
+package vcs
import (
"errors"
@@ -28,7 +28,7 @@ func TestRepoRootForImportPath(t *testing.T) {
{
"github.com/golang/groupcache",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://github.com/golang/groupcache",
},
},
@@ -41,14 +41,14 @@ func TestRepoRootForImportPath(t *testing.T) {
{
"hub.jazz.net/git/user1/pkgname",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://hub.jazz.net/git/user1/pkgname",
},
},
{
"hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://hub.jazz.net/git/user1/pkgname",
},
},
@@ -89,7 +89,7 @@ func TestRepoRootForImportPath(t *testing.T) {
{
"hub.jazz.net/git/user/pkg.name",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://hub.jazz.net/git/user/pkg.name",
},
},
@@ -102,7 +102,7 @@ func TestRepoRootForImportPath(t *testing.T) {
{
"git.openstack.org/openstack/swift",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://git.openstack.org/openstack/swift",
},
},
@@ -112,14 +112,14 @@ func TestRepoRootForImportPath(t *testing.T) {
{
"git.openstack.org/openstack/swift.git",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://git.openstack.org/openstack/swift.git",
},
},
{
"git.openstack.org/openstack/swift/go/hummingbird",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://git.openstack.org/openstack/swift",
},
},
@@ -148,21 +148,21 @@ func TestRepoRootForImportPath(t *testing.T) {
{
"git.apache.org/package-name.git",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://git.apache.org/package-name.git",
},
},
{
"git.apache.org/package-name_2.x.git/path/to/lib",
&RepoRoot{
- vcs: vcsGit,
+ VCS: vcsGit,
Repo: "https://git.apache.org/package-name_2.x.git",
},
},
{
"chiselapp.com/user/kyle/repository/fossilgg",
&RepoRoot{
- vcs: vcsFossil,
+ VCS: vcsFossil,
Repo: "https://chiselapp.com/user/kyle/repository/fossilgg",
},
},
@@ -191,8 +191,8 @@ func TestRepoRootForImportPath(t *testing.T) {
t.Errorf("RepoRootForImportPath(%q): %v", test.path, err)
continue
}
- if got.vcs.name != want.vcs.name || got.Repo != want.Repo {
- t.Errorf("RepoRootForImportPath(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.Repo, want.vcs, want.Repo)
+ if got.VCS.Name != want.VCS.Name || got.Repo != want.Repo {
+ t.Errorf("RepoRootForImportPath(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.VCS, got.Repo, want.VCS, want.Repo)
}
}
}
@@ -206,7 +206,7 @@ func TestFromDir(t *testing.T) {
defer os.RemoveAll(tempDir)
for j, vcs := range vcsList {
- dir := filepath.Join(tempDir, "example.com", vcs.name, "."+vcs.cmd)
+ dir := filepath.Join(tempDir, "example.com", vcs.Name, "."+vcs.Cmd)
if j&1 == 0 {
err := os.MkdirAll(dir, 0755)
if err != nil {
@@ -225,24 +225,24 @@ func TestFromDir(t *testing.T) {
}
want := RepoRoot{
- vcs: vcs,
- Root: path.Join("example.com", vcs.name),
+ VCS: vcs,
+ Root: path.Join("example.com", vcs.Name),
}
var got RepoRoot
- got.vcs, got.Root, err = vcsFromDir(dir, tempDir)
+ got.VCS, got.Root, err = FromDir(dir, tempDir)
if err != nil {
t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
continue
}
- if got.vcs.name != want.vcs.name || got.Root != want.Root {
- t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", dir, tempDir, got.vcs, got.Root, want.vcs, want.Root)
+ if got.VCS.Name != want.VCS.Name || got.Root != want.Root {
+ t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", dir, tempDir, got.VCS, got.Root, want.VCS, want.Root)
}
}
}
func TestIsSecure(t *testing.T) {
tests := []struct {
- vcs *vcsCmd
+ vcs *Cmd
url string
secure bool
}{
@@ -267,7 +267,7 @@ func TestIsSecure(t *testing.T) {
}
for _, test := range tests {
- secure := test.vcs.isSecure(test.url)
+ secure := test.vcs.IsSecure(test.url)
if secure != test.secure {
t.Errorf("%s isSecure(%q) = %t; want %t", test.vcs, test.url, secure, test.secure)
}
@@ -276,7 +276,7 @@ func TestIsSecure(t *testing.T) {
func TestIsSecureGitAllowProtocol(t *testing.T) {
tests := []struct {
- vcs *vcsCmd
+ vcs *Cmd
url string
secure bool
}{
@@ -307,7 +307,7 @@ func TestIsSecureGitAllowProtocol(t *testing.T) {
defer os.Unsetenv("GIT_ALLOW_PROTOCOL")
os.Setenv("GIT_ALLOW_PROTOCOL", "https:foo")
for _, test := range tests {
- secure := test.vcs.isSecure(test.url)
+ secure := test.vcs.IsSecure(test.url)
if secure != test.secure {
t.Errorf("%s isSecure(%q) = %t; want %t", test.vcs, test.url, secure, test.secure)
}