1
0
mirror of https://github.com/golang/go synced 2024-11-21 23:24:41 -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:
Daniel Krech 2012-02-13 23:46:31 -05:00 committed by Russ Cox
parent 222e2ee4d5
commit dcf5ca706b

View File

@ -27,6 +27,9 @@ type vcsCmd struct {
tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd
tagSyncCmd string // command to sync to specific tag tagSyncCmd string // command to sync to specific tag
tagSyncDefault string // command to sync to default tag tagSyncDefault string // command to sync to default tag
scheme []string
pingCmd string
} }
// A tagCmd describes a command to list available tags // A tagCmd describes a command to list available tags
@ -74,6 +77,9 @@ var vcsHg = &vcsCmd{
}, },
tagSyncCmd: "update -r {tag}", tagSyncCmd: "update -r {tag}",
tagSyncDefault: "update default", tagSyncDefault: "update default",
scheme: []string{"https", "http"},
pingCmd: "identify {scheme}://{repo}",
} }
// vcsGit describes how to use Git. // vcsGit describes how to use Git.
@ -94,6 +100,9 @@ var vcsGit = &vcsCmd{
}, },
tagSyncCmd: "checkout {tag}", tagSyncCmd: "checkout {tag}",
tagSyncDefault: "checkout origin/master", tagSyncDefault: "checkout origin/master",
scheme: []string{"git", "https", "http"},
pingCmd: "ls-remote {scheme}://{repo}",
} }
// vcsBzr describes how to use Bazaar. // vcsBzr describes how to use Bazaar.
@ -110,6 +119,9 @@ var vcsBzr = &vcsCmd{
tagCmd: []tagCmd{{"tags", `^(\S+)`}}, tagCmd: []tagCmd{{"tags", `^(\S+)`}},
tagSyncCmd: "update -r {tag}", tagSyncCmd: "update -r {tag}",
tagSyncDefault: "update -r revno:-1", tagSyncDefault: "update -r revno:-1",
scheme: []string{"https", "http", "bzr"},
pingCmd: "info {scheme}://{repo}",
} }
// vcsSvn describes how to use Subversion. // vcsSvn describes how to use Subversion.
@ -122,6 +134,9 @@ var vcsSvn = &vcsCmd{
// There is no tag command in subversion. // There is no tag command in subversion.
// The branch information is all in the path names. // The branch information is all in the path names.
scheme: []string{"https", "http", "svn"},
pingCmd: "info {scheme}://{repo}",
} }
func (v *vcsCmd) String() string { func (v *vcsCmd) String() string {
@ -136,17 +151,23 @@ func (v *vcsCmd) String() string {
// command's combined stdout+stderr to standard error. // command's combined stdout+stderr to standard error.
// Otherwise run discards the command's output. // Otherwise run discards the command's output.
func (v *vcsCmd) run(dir string, cmd string, keyval ...string) error { 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 return err
} }
// runOutput is like run but returns the output of the command. // 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 *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. // 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) m := make(map[string]string)
for i := 0; i < len(keyval); i += 2 { for i := 0; i < len(keyval); i += 2 {
m[keyval[i]] = keyval[i+1] 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() err := cmd.Run()
out := buf.Bytes() out := buf.Bytes()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " ")) if verbose || buildV {
os.Stderr.Write(out) fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
os.Stderr.Write(out)
}
return nil, err return nil, err
} }
return out, nil 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. // create creates a new copy of repo in dir.
// The parent of dir must exist; dir must not. // The parent of dir must exist; dir must not.
func (v *vcsCmd) create(dir, repo string) error { 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) repo string // repository to use (expand with match of re)
vcs string // version control system 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 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 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 { if vcs == nil {
return nil, "", "", fmt.Errorf("unknown version control system %q", match["vcs"]) 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 vcs, match["repo"], match["root"], nil
} }
return nil, "", "", fmt.Errorf("unrecognized import path %q", importPath) return nil, "", "", fmt.Errorf("unrecognized import path %q", importPath)
@ -340,7 +377,8 @@ var vcsPaths = []*vcsPath{
// General syntax for any server. // 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,
}, },
} }