mirror of
https://github.com/golang/go
synced 2024-11-22 03:54:39 -07:00
goinstall: select the tag that is closest to runtime.Version
release.r50 looks for newest tag <= go.r50 weekly.2010-10-10 looks for newest tag <= go.2010-10-10 Implements behavior for hg, git, and bzr. R=dsymonds, rsc, n13m3y3r CC=golang-dev https://golang.org/cl/4873057
This commit is contained in:
parent
596bf61d6c
commit
58b05e2448
@ -11,3 +11,9 @@ GOFILES=\
|
|||||||
make.go\
|
make.go\
|
||||||
|
|
||||||
include ../../Make.cmd
|
include ../../Make.cmd
|
||||||
|
|
||||||
|
test:
|
||||||
|
gotest
|
||||||
|
|
||||||
|
testshort:
|
||||||
|
gotest -test.short
|
||||||
|
@ -94,8 +94,11 @@ attempt to fetch updates. The -u flag changes this behavior,
|
|||||||
causing goinstall to update all remote packages encountered during
|
causing goinstall to update all remote packages encountered during
|
||||||
the installation.
|
the installation.
|
||||||
|
|
||||||
When downloading or updating, goinstall first looks for a tag or branch
|
When downloading or updating, goinstall looks for a tag with the "go." prefix
|
||||||
named "release". If there is one, it uses that version of the code.
|
that corresponds to the local Go version. For Go "release.r58" it looks for a
|
||||||
|
tag named "go.r58". For "weekly.2011-06-03" it looks for "go.weekly.2011-06-03".
|
||||||
|
If the specific "go.X" tag is not found, it chooses the closest earlier version.
|
||||||
|
If an appropriate tag is found, goinstall uses that version of the code.
|
||||||
Otherwise it uses the default version selected by the version control
|
Otherwise it uses the default version selected by the version control
|
||||||
system, typically HEAD for git, tip for Mercurial.
|
system, typically HEAD for git, tip for Mercurial.
|
||||||
|
|
||||||
|
@ -7,12 +7,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"exec"
|
"exec"
|
||||||
"fmt"
|
"fmt"
|
||||||
"http"
|
"http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,22 +39,21 @@ func maybeReportToDashboard(path string) {
|
|||||||
// 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 {
|
||||||
name string
|
name string
|
||||||
cmd string
|
cmd string
|
||||||
metadir string
|
metadir string
|
||||||
checkout string
|
checkout string
|
||||||
clone string
|
clone string
|
||||||
update string
|
update string
|
||||||
updateReleaseFlag string
|
updateRevFlag string
|
||||||
pull string
|
pull string
|
||||||
pullForceFlag string
|
pullForceFlag string
|
||||||
log string
|
tagList string
|
||||||
logLimitFlag string
|
tagListRe *regexp.Regexp
|
||||||
logReleaseFlag string
|
check string
|
||||||
check string
|
protocols []string
|
||||||
protocols []string
|
suffix string
|
||||||
suffix string
|
defaultHosts []host
|
||||||
defaultHosts []host
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type host struct {
|
type host struct {
|
||||||
@ -61,20 +63,18 @@ type host struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var hg = vcs{
|
var hg = vcs{
|
||||||
name: "Mercurial",
|
name: "Mercurial",
|
||||||
cmd: "hg",
|
cmd: "hg",
|
||||||
metadir: ".hg",
|
metadir: ".hg",
|
||||||
checkout: "checkout",
|
checkout: "checkout",
|
||||||
clone: "clone",
|
clone: "clone",
|
||||||
update: "update",
|
update: "update",
|
||||||
updateReleaseFlag: "release",
|
pull: "pull",
|
||||||
pull: "pull",
|
tagList: "tags",
|
||||||
log: "log",
|
tagListRe: regexp.MustCompile("([^ ]+)[^\n]+\n"),
|
||||||
logLimitFlag: "-l1",
|
check: "identify",
|
||||||
logReleaseFlag: "-rrelease",
|
protocols: []string{"https", "http"},
|
||||||
check: "identify",
|
suffix: ".hg",
|
||||||
protocols: []string{"https", "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", ""},
|
||||||
@ -82,20 +82,18 @@ var hg = vcs{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var git = vcs{
|
var git = vcs{
|
||||||
name: "Git",
|
name: "Git",
|
||||||
cmd: "git",
|
cmd: "git",
|
||||||
metadir: ".git",
|
metadir: ".git",
|
||||||
checkout: "checkout",
|
checkout: "checkout",
|
||||||
clone: "clone",
|
clone: "clone",
|
||||||
update: "pull",
|
update: "pull",
|
||||||
updateReleaseFlag: "release",
|
pull: "fetch",
|
||||||
pull: "fetch",
|
tagList: "tag",
|
||||||
log: "show-ref",
|
tagListRe: regexp.MustCompile("([^\n]+)\n"),
|
||||||
logLimitFlag: "",
|
check: "ls-remote",
|
||||||
logReleaseFlag: "release",
|
protocols: []string{"git", "https", "http"},
|
||||||
check: "ls-remote",
|
suffix: ".git",
|
||||||
protocols: []string{"git", "https", "http"},
|
|
||||||
suffix: ".git",
|
|
||||||
defaultHosts: []host{
|
defaultHosts: []host{
|
||||||
{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/git)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
|
{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/git)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
|
||||||
{regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ".git"},
|
{regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ".git"},
|
||||||
@ -103,40 +101,35 @@ var git = vcs{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var svn = vcs{
|
var svn = vcs{
|
||||||
name: "Subversion",
|
name: "Subversion",
|
||||||
cmd: "svn",
|
cmd: "svn",
|
||||||
metadir: ".svn",
|
metadir: ".svn",
|
||||||
checkout: "checkout",
|
checkout: "checkout",
|
||||||
clone: "checkout",
|
clone: "checkout",
|
||||||
update: "update",
|
update: "update",
|
||||||
updateReleaseFlag: "release",
|
check: "info",
|
||||||
log: "log",
|
protocols: []string{"https", "http", "svn"},
|
||||||
logLimitFlag: "-l1",
|
suffix: ".svn",
|
||||||
logReleaseFlag: "release",
|
|
||||||
check: "info",
|
|
||||||
protocols: []string{"https", "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", ""},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var bzr = vcs{
|
var bzr = vcs{
|
||||||
name: "Bazaar",
|
name: "Bazaar",
|
||||||
cmd: "bzr",
|
cmd: "bzr",
|
||||||
metadir: ".bzr",
|
metadir: ".bzr",
|
||||||
checkout: "update",
|
checkout: "update",
|
||||||
clone: "branch",
|
clone: "branch",
|
||||||
update: "update",
|
update: "update",
|
||||||
updateReleaseFlag: "-rrelease",
|
updateRevFlag: "-r",
|
||||||
pull: "pull",
|
pull: "pull",
|
||||||
pullForceFlag: "--overwrite",
|
pullForceFlag: "--overwrite",
|
||||||
log: "log",
|
tagList: "tags",
|
||||||
logLimitFlag: "-l1",
|
tagListRe: regexp.MustCompile("([^ ]+)[^\n]+\n"),
|
||||||
logReleaseFlag: "-rrelease",
|
check: "info",
|
||||||
check: "info",
|
protocols: []string{"https", "http", "bzr"},
|
||||||
protocols: []string{"https", "http", "bzr"},
|
suffix: ".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", ""},
|
||||||
},
|
},
|
||||||
@ -240,20 +233,84 @@ func download(pkg, srcDir string) (public bool, err os.Error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to detect if a "release" tag exists. If it does, update
|
// updateRepo gets a list of tags in the repository and
|
||||||
// to the tagged version, otherwise just update the current branch.
|
// checks out the tag closest to the current runtime.Version.
|
||||||
// NOTE(_nil): svn will always fail because it is trying to get
|
// If no matching tag is found, it just updates to tip.
|
||||||
// the revision history of a file named "release" instead of
|
|
||||||
// looking for a commit with a release tag
|
|
||||||
func (v *vcs) updateRepo(dst string) os.Error {
|
func (v *vcs) updateRepo(dst string) os.Error {
|
||||||
if err := quietRun(dst, nil, v.cmd, v.log, v.logLimitFlag, v.logReleaseFlag); err == nil {
|
if v.tagList == "" || v.tagListRe == nil {
|
||||||
if err := run(dst, nil, v.cmd, v.checkout, v.updateReleaseFlag); err != nil {
|
// TODO(adg): fix for svn
|
||||||
return err
|
return run(dst, nil, v.cmd, v.update)
|
||||||
}
|
}
|
||||||
} else if err := run(dst, nil, v.cmd, v.update); err != nil {
|
|
||||||
|
// Get tag list.
|
||||||
|
stderr := new(bytes.Buffer)
|
||||||
|
cmd := exec.Command(v.cmd, v.tagList)
|
||||||
|
cmd.Dir = dst
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
b, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
errorf("%s %s: %s\n", v.cmd, v.tagList, stderr)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
var tags []string
|
||||||
|
for _, m := range v.tagListRe.FindAllStringSubmatch(string(b), -1) {
|
||||||
|
tags = append(tags, m[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only use the tag component of runtime.Version.
|
||||||
|
ver := strings.Split(runtime.Version(), " ")[0]
|
||||||
|
|
||||||
|
// Select tag.
|
||||||
|
if tag := selectTag(ver, tags); tag != "" {
|
||||||
|
printf("selecting revision %q\n", tag)
|
||||||
|
return run(dst, nil, v.cmd, v.checkout, v.updateRevFlag+tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// No matching tag found, make default selection.
|
||||||
|
printf("selecting tip\n")
|
||||||
|
return run(dst, nil, v.cmd, v.update)
|
||||||
|
}
|
||||||
|
|
||||||
|
// selectTag returns the closest matching tag for a given version.
|
||||||
|
// Closest means the latest one that is not after the current release.
|
||||||
|
// Version "release.rN" matches tags of the form "go.rN" (N being a decimal).
|
||||||
|
// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
|
||||||
|
func selectTag(goVersion string, tags []string) (match string) {
|
||||||
|
const rPrefix = "release.r"
|
||||||
|
if strings.HasPrefix(goVersion, rPrefix) {
|
||||||
|
p := "go.r"
|
||||||
|
v, err := strconv.Atof64(goVersion[len(rPrefix):])
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var matchf float64
|
||||||
|
for _, t := range tags {
|
||||||
|
if !strings.HasPrefix(t, p) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tf, err := strconv.Atof64(t[len(p):])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if matchf < tf && tf <= v {
|
||||||
|
match, matchf = t, tf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const wPrefix = "weekly."
|
||||||
|
if strings.HasPrefix(goVersion, wPrefix) {
|
||||||
|
p := "go.weekly."
|
||||||
|
v := goVersion[len(wPrefix):]
|
||||||
|
for _, t := range tags {
|
||||||
|
if !strings.HasPrefix(t, p) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if match < t && t[len(p):] <= v {
|
||||||
|
match = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkoutRepo checks out repo into dst using vcs.
|
// checkoutRepo checks out repo into dst using vcs.
|
||||||
|
73
src/cmd/goinstall/tag_test.go
Normal file
73
src/cmd/goinstall/tag_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Copyright 2011 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 main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
var selectTagTestTags = []string{
|
||||||
|
"go.r58",
|
||||||
|
"go.r58.1",
|
||||||
|
"go.r59",
|
||||||
|
"go.r59.1",
|
||||||
|
"go.r61",
|
||||||
|
"go.r61.1",
|
||||||
|
"go.weekly.2010-01-02",
|
||||||
|
"go.weekly.2011-10-12",
|
||||||
|
"go.weekly.2011-10-12.1",
|
||||||
|
"go.weekly.2011-10-14",
|
||||||
|
"go.weekly.2011-11-01",
|
||||||
|
// these should be ignored:
|
||||||
|
"release.r59",
|
||||||
|
"release.r59.1",
|
||||||
|
"release",
|
||||||
|
"weekly.2011-10-12",
|
||||||
|
"weekly.2011-10-12.1",
|
||||||
|
"weekly",
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"go.f00",
|
||||||
|
"go!r60",
|
||||||
|
"go.1999-01-01",
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectTagTests = []struct {
|
||||||
|
version string
|
||||||
|
selected string
|
||||||
|
}{
|
||||||
|
{"release.r57", ""},
|
||||||
|
{"release.r58.2", "go.r58.1"},
|
||||||
|
{"release.r59", "go.r59"},
|
||||||
|
{"release.r59.1", "go.r59.1"},
|
||||||
|
{"release.r60", "go.r59.1"},
|
||||||
|
{"release.r60.1", "go.r59.1"},
|
||||||
|
{"release.r61", "go.r61"},
|
||||||
|
{"release.r66", "go.r61.1"},
|
||||||
|
{"weekly.2010-01-01", ""},
|
||||||
|
{"weekly.2010-01-02", "go.weekly.2010-01-02"},
|
||||||
|
{"weekly.2010-01-02.1", "go.weekly.2010-01-02"},
|
||||||
|
{"weekly.2010-01-03", "go.weekly.2010-01-02"},
|
||||||
|
{"weekly.2011-10-12", "go.weekly.2011-10-12"},
|
||||||
|
{"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"},
|
||||||
|
{"weekly.2011-10-13", "go.weekly.2011-10-12.1"},
|
||||||
|
{"weekly.2011-10-14", "go.weekly.2011-10-14"},
|
||||||
|
{"weekly.2011-10-14.1", "go.weekly.2011-10-14"},
|
||||||
|
{"weekly.2011-11-01", "go.weekly.2011-11-01"},
|
||||||
|
{"weekly.2014-01-01", "go.weekly.2011-11-01"},
|
||||||
|
{"weekly.3000-01-01", "go.weekly.2011-11-01"},
|
||||||
|
// faulty versions:
|
||||||
|
{"release.f00", ""},
|
||||||
|
{"weekly.1999-01-01", ""},
|
||||||
|
{"junk", ""},
|
||||||
|
{"", ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectTag(t *testing.T) {
|
||||||
|
for _, c := range selectTagTests {
|
||||||
|
selected := selectTag(c.version, selectTagTestTags)
|
||||||
|
if selected != c.selected {
|
||||||
|
t.Errorf("selectTag(%q) = %q, want %q", c.version, selected, c.selected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -218,7 +218,6 @@ NOTEST+=\
|
|||||||
../cmd/cgo\
|
../cmd/cgo\
|
||||||
../cmd/ebnflint\
|
../cmd/ebnflint\
|
||||||
../cmd/godoc\
|
../cmd/godoc\
|
||||||
../cmd/goinstall\
|
|
||||||
../cmd/gotest\
|
../cmd/gotest\
|
||||||
../cmd/goyacc\
|
../cmd/goyacc\
|
||||||
../cmd/hgpatch\
|
../cmd/hgpatch\
|
||||||
|
Loading…
Reference in New Issue
Block a user