mirror of
https://github.com/golang/go
synced 2024-11-19 16:34:49 -07:00
goinstall: Add support for generic hosts using special import form
This change extends goinstall to support "magic" package names of the form: <host>/<repo>.<vcs>/<path> Where <host> is the hostname, <repo> the path to the repository, <vcs> the type of vcs (git, hg, bzr or svn), and <path> is the path inside the repository that contains the source code for the package. For example: "example.com/pub/foo.hg/src" means download the Mercurial repository at either pub/foo.hg or pub/foo from example.com and then build and install the source files from src inside the repository checkout. Repositories on the built-in hostings sites (github, bitbucket, launchpad and googlecode) must still use the old form (i.e. github.com/xxx/yyy.git/src will be rejected). R=adg, rsc CC=golang-dev https://golang.org/cl/4626064
This commit is contained in:
parent
369418d29c
commit
8ffbc4016a
@ -7,6 +7,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"exec"
|
||||||
"http"
|
"http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -34,6 +35,7 @@ func maybeReportToDashboard(path string) {
|
|||||||
type host struct {
|
type host struct {
|
||||||
pattern *regexp.Regexp
|
pattern *regexp.Regexp
|
||||||
protocol string
|
protocol string
|
||||||
|
suffix string
|
||||||
}
|
}
|
||||||
|
|
||||||
// a vcs represents a version control system
|
// a vcs represents a version control system
|
||||||
@ -76,9 +78,10 @@ var hg = vcs{
|
|||||||
logReleaseFlag: "-rrelease",
|
logReleaseFlag: "-rrelease",
|
||||||
check: "identify",
|
check: "identify",
|
||||||
protocols: []string{"http"},
|
protocols: []string{"http"},
|
||||||
|
suffix: ".hg",
|
||||||
defaultHosts: []host{
|
defaultHosts: []host{
|
||||||
{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/hg)(/[a-z0-9A-Z_.\-/]*)?$`), "https"},
|
{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/hg)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
|
||||||
{regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http"},
|
{regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ""},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +101,7 @@ var git = vcs{
|
|||||||
protocols: []string{"git", "http"},
|
protocols: []string{"git", "http"},
|
||||||
suffix: ".git",
|
suffix: ".git",
|
||||||
defaultHosts: []host{
|
defaultHosts: []host{
|
||||||
{regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http"},
|
{regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ".git"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,8 +118,9 @@ var svn = vcs{
|
|||||||
logReleaseFlag: "release",
|
logReleaseFlag: "release",
|
||||||
check: "info",
|
check: "info",
|
||||||
protocols: []string{"http", "svn"},
|
protocols: []string{"http", "svn"},
|
||||||
|
suffix: ".svn",
|
||||||
defaultHosts: []host{
|
defaultHosts: []host{
|
||||||
{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/svn)(/[a-z0-9A-Z_.\-/]*)?$`), "https"},
|
{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/svn)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,13 +139,40 @@ var bzr = vcs{
|
|||||||
logReleaseFlag: "-rrelease",
|
logReleaseFlag: "-rrelease",
|
||||||
check: "info",
|
check: "info",
|
||||||
protocols: []string{"http", "bzr"},
|
protocols: []string{"http", "bzr"},
|
||||||
|
suffix: ".bzr",
|
||||||
defaultHosts: []host{
|
defaultHosts: []host{
|
||||||
{regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`), "https"},
|
{regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`), "https", ""},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var vcsList = []*vcs{&git, &hg, &bzr, &svn}
|
var vcsList = []*vcs{&git, &hg, &bzr, &svn}
|
||||||
|
|
||||||
|
func (v *vcs) findRepo(prefix string) *vcsMatch {
|
||||||
|
for _, proto := range v.protocols {
|
||||||
|
for _, suffix := range []string{v.suffix, ""} {
|
||||||
|
repo := proto + "://" + prefix + suffix
|
||||||
|
out, err := exec.Command(v.cmd, v.check, repo).CombinedOutput()
|
||||||
|
if err == nil {
|
||||||
|
return &vcsMatch{v, prefix + v.suffix, repo}
|
||||||
|
}
|
||||||
|
printf("find %s: %s %s %s: %v\n%s\n", prefix, v.cmd, v.check, repo, err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorf("find %s: couldn't find %s repository\n", prefix, v.name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findRepo(pkg string) *vcsMatch {
|
||||||
|
for _, v := range vcsList {
|
||||||
|
i := strings.Index(pkg+"/", v.suffix+"/")
|
||||||
|
if i >= 0 {
|
||||||
|
return v.findRepo(pkg[:i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// isRemote returns true if the first part of the package name looks like a
|
// isRemote returns true if the first part of the package name looks like a
|
||||||
// hostname - i.e. contains at least one '.' and the last part is at least 2
|
// hostname - i.e. contains at least one '.' and the last part is at least 2
|
||||||
// characters.
|
// characters.
|
||||||
@ -162,6 +193,7 @@ func download(pkg, srcDir string) os.Error {
|
|||||||
if strings.Contains(pkg, "..") {
|
if strings.Contains(pkg, "..") {
|
||||||
return os.NewError("invalid path (contains ..)")
|
return os.NewError("invalid path (contains ..)")
|
||||||
}
|
}
|
||||||
|
dashpath := pkg
|
||||||
var m *vcsMatch
|
var m *vcsMatch
|
||||||
for _, v := range vcsList {
|
for _, v := range vcsList {
|
||||||
for _, host := range v.defaultHosts {
|
for _, host := range v.defaultHosts {
|
||||||
@ -169,15 +201,19 @@ func download(pkg, srcDir string) os.Error {
|
|||||||
if v.suffix != "" && strings.HasSuffix(hm[1], v.suffix) {
|
if v.suffix != "" && strings.HasSuffix(hm[1], v.suffix) {
|
||||||
return os.NewError("repository " + pkg + " should not have " + v.suffix + " suffix")
|
return os.NewError("repository " + pkg + " should not have " + v.suffix + " suffix")
|
||||||
}
|
}
|
||||||
repo := host.protocol + "://" + hm[1] + v.suffix
|
repo := host.protocol + "://" + hm[1] + host.suffix
|
||||||
m = &vcsMatch{v, hm[1], repo}
|
m = &vcsMatch{v, hm[1], repo}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if m == nil {
|
||||||
|
m = findRepo(pkg)
|
||||||
|
dashpath = "" // don't report to dashboard
|
||||||
|
}
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return os.NewError("cannot download: " + pkg)
|
return os.NewError("cannot download: " + pkg)
|
||||||
}
|
}
|
||||||
return vcsCheckout(m.vcs, srcDir, m.prefix, m.repo, pkg)
|
return vcsCheckout(m.vcs, srcDir, m.prefix, m.repo, dashpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to detect if a "release" tag exists. If it does, update
|
// Try to detect if a "release" tag exists. If it does, update
|
||||||
@ -219,7 +255,9 @@ func vcsCheckout(vcs *vcs, srcDir, pkgprefix, repo, dashpath string) os.Error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// success on first installation - report
|
// success on first installation - report
|
||||||
maybeReportToDashboard(dashpath)
|
if dashpath != "" {
|
||||||
|
maybeReportToDashboard(dashpath)
|
||||||
|
}
|
||||||
} else if *update {
|
} else if *update {
|
||||||
// Retrieve new revisions from the remote branch, if the VCS
|
// Retrieve new revisions from the remote branch, if the VCS
|
||||||
// supports this operation independently (e.g. svn doesn't)
|
// supports this operation independently (e.g. svn doesn't)
|
||||||
|
Loading…
Reference in New Issue
Block a user