mirror of
https://github.com/golang/go
synced 2024-11-21 16:34:42 -07:00
cmd/go: go get scheme detection
Fixes #2895. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/5651055
This commit is contained in:
parent
222e2ee4d5
commit
dcf5ca706b
@ -27,6 +27,9 @@ type vcsCmd struct {
|
||||
tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd
|
||||
tagSyncCmd string // command to sync to specific tag
|
||||
tagSyncDefault string // command to sync to default tag
|
||||
|
||||
scheme []string
|
||||
pingCmd string
|
||||
}
|
||||
|
||||
// A tagCmd describes a command to list available tags
|
||||
@ -74,6 +77,9 @@ var vcsHg = &vcsCmd{
|
||||
},
|
||||
tagSyncCmd: "update -r {tag}",
|
||||
tagSyncDefault: "update default",
|
||||
|
||||
scheme: []string{"https", "http"},
|
||||
pingCmd: "identify {scheme}://{repo}",
|
||||
}
|
||||
|
||||
// vcsGit describes how to use Git.
|
||||
@ -94,6 +100,9 @@ var vcsGit = &vcsCmd{
|
||||
},
|
||||
tagSyncCmd: "checkout {tag}",
|
||||
tagSyncDefault: "checkout origin/master",
|
||||
|
||||
scheme: []string{"git", "https", "http"},
|
||||
pingCmd: "ls-remote {scheme}://{repo}",
|
||||
}
|
||||
|
||||
// vcsBzr describes how to use Bazaar.
|
||||
@ -110,6 +119,9 @@ var vcsBzr = &vcsCmd{
|
||||
tagCmd: []tagCmd{{"tags", `^(\S+)`}},
|
||||
tagSyncCmd: "update -r {tag}",
|
||||
tagSyncDefault: "update -r revno:-1",
|
||||
|
||||
scheme: []string{"https", "http", "bzr"},
|
||||
pingCmd: "info {scheme}://{repo}",
|
||||
}
|
||||
|
||||
// vcsSvn describes how to use Subversion.
|
||||
@ -122,6 +134,9 @@ var vcsSvn = &vcsCmd{
|
||||
|
||||
// There is no tag command in subversion.
|
||||
// The branch information is all in the path names.
|
||||
|
||||
scheme: []string{"https", "http", "svn"},
|
||||
pingCmd: "info {scheme}://{repo}",
|
||||
}
|
||||
|
||||
func (v *vcsCmd) String() string {
|
||||
@ -136,17 +151,23 @@ func (v *vcsCmd) String() string {
|
||||
// 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 {
|
||||
_, err := v.run1(dir, cmd, keyval)
|
||||
_, 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 {
|
||||
_, 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) {
|
||||
return v.run1(dir, cmd, keyval)
|
||||
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) ([]byte, error) {
|
||||
func (v *vcsCmd) 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]
|
||||
@ -168,13 +189,20 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string) ([]byte, erro
|
||||
err := cmd.Run()
|
||||
out := buf.Bytes()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
|
||||
os.Stderr.Write(out)
|
||||
if verbose || buildV {
|
||||
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
|
||||
os.Stderr.Write(out)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ping pings to determine scheme to use.
|
||||
func (v *vcsCmd) ping(scheme, repo string) error {
|
||||
return v.runVerboseOnly(".", v.pingCmd, "scheme", scheme, "repo", repo)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@ -236,6 +264,7 @@ type vcsPath struct {
|
||||
repo string // repository to use (expand with match of re)
|
||||
vcs string // version control system to use (expand with match of re)
|
||||
check func(match map[string]string) error // additional checks
|
||||
ping bool // ping for scheme to use to download repo
|
||||
|
||||
regexp *regexp.Regexp // cached compiled form of re
|
||||
}
|
||||
@ -283,6 +312,14 @@ func vcsForImportPath(importPath string) (vcs *vcsCmd, repo, root string, err er
|
||||
if vcs == nil {
|
||||
return nil, "", "", fmt.Errorf("unknown version control system %q", match["vcs"])
|
||||
}
|
||||
if srv.ping {
|
||||
for _, scheme := range vcs.scheme {
|
||||
if vcs.ping(scheme, match["repo"]) == nil {
|
||||
match["repo"] = scheme + "://" + match["repo"]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return vcs, match["repo"], match["root"], nil
|
||||
}
|
||||
return nil, "", "", fmt.Errorf("unrecognized import path %q", importPath)
|
||||
@ -340,7 +377,8 @@ var vcsPaths = []*vcsPath{
|
||||
|
||||
// General syntax for any server.
|
||||
{
|
||||
re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
|
||||
re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
|
||||
ping: true,
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user