1
0
mirror of https://github.com/golang/go synced 2024-10-03 03:21:22 -06:00

goinstall: support for Bazaar+Launchpad

With these changes, goinstall is now able to use branches
maintained with Bazaar located in Launchpad.

Project aliases such as /project and /project/series are
supported in addition to specific user or team branches
such as /~user/project/branch.  Temporary branches under
the +junk special project are also supported.

As a curious side effect, since Launchpad is able to import
code from other locations, they can be indirectly
accessible too if desired.

R=rsc
CC=golang-dev
https://golang.org/cl/1699050
This commit is contained in:
Gustavo Niemeyer 2010-06-30 23:33:49 -07:00 committed by Russ Cox
parent 88744a9733
commit ae33032893
3 changed files with 88 additions and 43 deletions

View File

@ -42,6 +42,15 @@ if necessary. The recognized code hosting sites are:
import "project.googlecode.com/svn/trunk" import "project.googlecode.com/svn/trunk"
import "project.googlecode.com/svn/trunk/sub/directory" import "project.googlecode.com/svn/trunk/sub/directory"
Launchpad
import "launchpad.net/project
import "launchpad.net/project/series
import "launchpad.net/project/series/sub/directory
import "launchpad.net/~user/project/branch
import "launchpad.net/~user/project/branch/sub/directory
If the destination directory (e.g., $GOROOT/src/pkg/bitbucket.org/user/project) If the destination directory (e.g., $GOROOT/src/pkg/bitbucket.org/user/project)
already exists and contains an appropriate checkout, goinstall will not already exists and contains an appropriate checkout, goinstall will not

View File

@ -34,6 +34,7 @@ func maybeReportToDashboard(path string) {
var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`) var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`)
var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`) var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`) var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
var launchpad = 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_.\-/]+)?$`)
// download checks out or updates pkg from the remote server. // download checks out or updates pkg from the remote server.
func download(pkg string) (string, os.Error) { func download(pkg string) (string, os.Error) {
@ -71,53 +72,78 @@ func download(pkg string) (string, os.Error) {
} }
return root + pkg, nil return root + pkg, nil
} }
if m := launchpad.MatchStrings(pkg); m != nil {
// Either lp.net/<project>[/<series>[/<path>]]
// or lp.net/~<user or team>/<project>/<branch>[/<path>]
if err := vcsCheckout(&bzr, root+m[1], "https://"+m[1], m[1]); err != nil {
return "", err
}
return root + pkg, nil
}
return "", os.ErrorString("unknown repository: " + pkg) return "", os.ErrorString("unknown repository: " + pkg)
} }
// a vcs represents a version control system // a vcs represents a version control system
// like Mercurial, Git, or Subversion. // like Mercurial, Git, or Subversion.
type vcs struct { type vcs struct {
cmd string cmd string
metadir string metadir string
clone string clone string
update string update string
pull string updateReleaseFlag string
log string pull string
logLimitFlag string pullForceFlag string
logReleaseFlag string log string
logLimitFlag string
logReleaseFlag string
} }
var hg = vcs{ var hg = vcs{
cmd: "hg", cmd: "hg",
metadir: ".hg", metadir: ".hg",
clone: "clone", clone: "clone",
update: "update", update: "update",
pull: "pull", updateReleaseFlag: "release",
log: "log", pull: "pull",
logLimitFlag: "-l1", log: "log",
logReleaseFlag: "-rrelease", logLimitFlag: "-l1",
logReleaseFlag: "-rrelease",
} }
var git = vcs{ var git = vcs{
cmd: "git", cmd: "git",
metadir: ".git", metadir: ".git",
clone: "clone", clone: "clone",
update: "pull", update: "pull",
pull: "fetch", updateReleaseFlag: "release",
log: "log", pull: "fetch",
logLimitFlag: "-n1", log: "log",
logReleaseFlag: "release", logLimitFlag: "-n1",
logReleaseFlag: "release",
} }
var svn = vcs{ var svn = vcs{
cmd: "svn", cmd: "svn",
metadir: ".svn", metadir: ".svn",
clone: "checkout", clone: "checkout",
update: "update", update: "update",
pull: "", updateReleaseFlag: "release",
log: "log", log: "log",
logLimitFlag: "-l1", logLimitFlag: "-l1",
logReleaseFlag: "release", logReleaseFlag: "release",
}
var bzr = vcs{
cmd: "bzr",
metadir: ".bzr",
clone: "branch",
update: "update",
updateReleaseFlag: "-rrelease",
pull: "pull",
pullForceFlag: "--overwrite",
log: "log",
logLimitFlag: "-l1",
logReleaseFlag: "-rrelease",
} }
// vcsCheckout checks out repo into dst using vcs. // vcsCheckout checks out repo into dst using vcs.
@ -138,27 +164,37 @@ func vcsCheckout(vcs *vcs, dst, repo, dashpath string) os.Error {
if err := run("/", nil, vcs.cmd, vcs.clone, repo, dst); err != nil { if err := run("/", nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
return err return err
} }
quietRun(dst, nil, vcs.cmd, vcs.update, "release") quietRun(dst, nil, vcs.cmd, vcs.update, vcs.updateReleaseFlag)
// success on first installation - report // success on first installation - report
maybeReportToDashboard(dashpath) maybeReportToDashboard(dashpath)
} else if *update { } else if *update {
// Retrieve new revisions from the remote branch, if the VCS
// supports this operation independently (e.g. svn doesn't)
if vcs.pull != "" { if vcs.pull != "" {
if err := run(dst, nil, vcs.cmd, vcs.pull); err != nil { if vcs.pullForceFlag != "" {
if err := run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
return err
}
} else if err := run(dst, nil, vcs.cmd, vcs.pull); err != nil {
return err return err
} }
} }
// check for release with hg log -l 1 -r release
// if success, hg update release // Try to detect if a "release" tag exists. If it does, update
// else hg update // to the tagged version. If no tag is found, then update to the
// tip afterwards.
// NOTE(gustavo@niemeyer.net): What is the expected behavior with
// svn here? "svn log -l1 release" doesn't make sense in this
// context and will probably fail.
if err := quietRun(dst, nil, vcs.cmd, vcs.log, vcs.logLimitFlag, vcs.logReleaseFlag); err == nil { if err := quietRun(dst, nil, vcs.cmd, vcs.log, vcs.logLimitFlag, vcs.logReleaseFlag); err == nil {
if err := run(dst, nil, vcs.cmd, vcs.update, "release"); err != nil { if err := run(dst, nil, vcs.cmd, vcs.update, vcs.updateReleaseFlag); err != nil {
return err // The VCS supports tagging, has the "release" tag, but
} // something else went wrong. Report.
} else {
if err := run(dst, nil, vcs.cmd, vcs.update); err != nil {
return err return err
} }
} else if err := run(dst, nil, vcs.cmd, vcs.update); err != nil {
return err
} }
} }
return nil return nil

View File

@ -184,7 +184,7 @@ func quietRun(dir string, stdin []byte, cmd ...string) os.Error {
return genRun(dir, stdin, cmd, true) return genRun(dir, stdin, cmd, true)
} }
// genRun implements run and tryRun. // genRun implements run and quietRun.
func genRun(dir string, stdin []byte, cmd []string, quiet bool) os.Error { func genRun(dir string, stdin []byte, cmd []string, quiet bool) os.Error {
bin, err := exec.LookPath(cmd[0]) bin, err := exec.LookPath(cmd[0])
if err != nil { if err != nil {