mirror of
https://github.com/golang/go
synced 2024-11-21 15:24:45 -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\
|
||||
|
||||
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
|
||||
the installation.
|
||||
|
||||
When downloading or updating, goinstall first looks for a tag or branch
|
||||
named "release". If there is one, it uses that version of the code.
|
||||
When downloading or updating, goinstall looks for a tag with the "go." prefix
|
||||
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
|
||||
system, typically HEAD for git, tip for Mercurial.
|
||||
|
||||
|
@ -7,12 +7,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"exec"
|
||||
"fmt"
|
||||
"http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -36,22 +39,21 @@ func maybeReportToDashboard(path string) {
|
||||
// a vcs represents a version control system
|
||||
// like Mercurial, Git, or Subversion.
|
||||
type vcs struct {
|
||||
name string
|
||||
cmd string
|
||||
metadir string
|
||||
checkout string
|
||||
clone string
|
||||
update string
|
||||
updateReleaseFlag string
|
||||
pull string
|
||||
pullForceFlag string
|
||||
log string
|
||||
logLimitFlag string
|
||||
logReleaseFlag string
|
||||
check string
|
||||
protocols []string
|
||||
suffix string
|
||||
defaultHosts []host
|
||||
name string
|
||||
cmd string
|
||||
metadir string
|
||||
checkout string
|
||||
clone string
|
||||
update string
|
||||
updateRevFlag string
|
||||
pull string
|
||||
pullForceFlag string
|
||||
tagList string
|
||||
tagListRe *regexp.Regexp
|
||||
check string
|
||||
protocols []string
|
||||
suffix string
|
||||
defaultHosts []host
|
||||
}
|
||||
|
||||
type host struct {
|
||||
@ -61,20 +63,18 @@ type host struct {
|
||||
}
|
||||
|
||||
var hg = vcs{
|
||||
name: "Mercurial",
|
||||
cmd: "hg",
|
||||
metadir: ".hg",
|
||||
checkout: "checkout",
|
||||
clone: "clone",
|
||||
update: "update",
|
||||
updateReleaseFlag: "release",
|
||||
pull: "pull",
|
||||
log: "log",
|
||||
logLimitFlag: "-l1",
|
||||
logReleaseFlag: "-rrelease",
|
||||
check: "identify",
|
||||
protocols: []string{"https", "http"},
|
||||
suffix: ".hg",
|
||||
name: "Mercurial",
|
||||
cmd: "hg",
|
||||
metadir: ".hg",
|
||||
checkout: "checkout",
|
||||
clone: "clone",
|
||||
update: "update",
|
||||
pull: "pull",
|
||||
tagList: "tags",
|
||||
tagListRe: regexp.MustCompile("([^ ]+)[^\n]+\n"),
|
||||
check: "identify",
|
||||
protocols: []string{"https", "http"},
|
||||
suffix: ".hg",
|
||||
defaultHosts: []host{
|
||||
{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", ""},
|
||||
@ -82,20 +82,18 @@ var hg = vcs{
|
||||
}
|
||||
|
||||
var git = vcs{
|
||||
name: "Git",
|
||||
cmd: "git",
|
||||
metadir: ".git",
|
||||
checkout: "checkout",
|
||||
clone: "clone",
|
||||
update: "pull",
|
||||
updateReleaseFlag: "release",
|
||||
pull: "fetch",
|
||||
log: "show-ref",
|
||||
logLimitFlag: "",
|
||||
logReleaseFlag: "release",
|
||||
check: "ls-remote",
|
||||
protocols: []string{"git", "https", "http"},
|
||||
suffix: ".git",
|
||||
name: "Git",
|
||||
cmd: "git",
|
||||
metadir: ".git",
|
||||
checkout: "checkout",
|
||||
clone: "clone",
|
||||
update: "pull",
|
||||
pull: "fetch",
|
||||
tagList: "tag",
|
||||
tagListRe: regexp.MustCompile("([^\n]+)\n"),
|
||||
check: "ls-remote",
|
||||
protocols: []string{"git", "https", "http"},
|
||||
suffix: ".git",
|
||||
defaultHosts: []host{
|
||||
{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"},
|
||||
@ -103,40 +101,35 @@ var git = vcs{
|
||||
}
|
||||
|
||||
var svn = vcs{
|
||||
name: "Subversion",
|
||||
cmd: "svn",
|
||||
metadir: ".svn",
|
||||
checkout: "checkout",
|
||||
clone: "checkout",
|
||||
update: "update",
|
||||
updateReleaseFlag: "release",
|
||||
log: "log",
|
||||
logLimitFlag: "-l1",
|
||||
logReleaseFlag: "release",
|
||||
check: "info",
|
||||
protocols: []string{"https", "http", "svn"},
|
||||
suffix: ".svn",
|
||||
name: "Subversion",
|
||||
cmd: "svn",
|
||||
metadir: ".svn",
|
||||
checkout: "checkout",
|
||||
clone: "checkout",
|
||||
update: "update",
|
||||
check: "info",
|
||||
protocols: []string{"https", "http", "svn"},
|
||||
suffix: ".svn",
|
||||
defaultHosts: []host{
|
||||
{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/svn)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
|
||||
},
|
||||
}
|
||||
|
||||
var bzr = vcs{
|
||||
name: "Bazaar",
|
||||
cmd: "bzr",
|
||||
metadir: ".bzr",
|
||||
checkout: "update",
|
||||
clone: "branch",
|
||||
update: "update",
|
||||
updateReleaseFlag: "-rrelease",
|
||||
pull: "pull",
|
||||
pullForceFlag: "--overwrite",
|
||||
log: "log",
|
||||
logLimitFlag: "-l1",
|
||||
logReleaseFlag: "-rrelease",
|
||||
check: "info",
|
||||
protocols: []string{"https", "http", "bzr"},
|
||||
suffix: ".bzr",
|
||||
name: "Bazaar",
|
||||
cmd: "bzr",
|
||||
metadir: ".bzr",
|
||||
checkout: "update",
|
||||
clone: "branch",
|
||||
update: "update",
|
||||
updateRevFlag: "-r",
|
||||
pull: "pull",
|
||||
pullForceFlag: "--overwrite",
|
||||
tagList: "tags",
|
||||
tagListRe: regexp.MustCompile("([^ ]+)[^\n]+\n"),
|
||||
check: "info",
|
||||
protocols: []string{"https", "http", "bzr"},
|
||||
suffix: ".bzr",
|
||||
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", ""},
|
||||
},
|
||||
@ -240,20 +233,84 @@ func download(pkg, srcDir string) (public bool, err os.Error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Try to detect if a "release" tag exists. If it does, update
|
||||
// to the tagged version, otherwise just update the current branch.
|
||||
// NOTE(_nil): svn will always fail because it is trying to get
|
||||
// the revision history of a file named "release" instead of
|
||||
// looking for a commit with a release tag
|
||||
// updateRepo gets a list of tags in the repository and
|
||||
// checks out the tag closest to the current runtime.Version.
|
||||
// If no matching tag is found, it just updates to tip.
|
||||
func (v *vcs) updateRepo(dst string) os.Error {
|
||||
if err := quietRun(dst, nil, v.cmd, v.log, v.logLimitFlag, v.logReleaseFlag); err == nil {
|
||||
if err := run(dst, nil, v.cmd, v.checkout, v.updateReleaseFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := run(dst, nil, v.cmd, v.update); err != nil {
|
||||
if v.tagList == "" || v.tagListRe == nil {
|
||||
// TODO(adg): fix for svn
|
||||
return run(dst, nil, v.cmd, v.update)
|
||||
}
|
||||
|
||||
// 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 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.
|
||||
|
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/ebnflint\
|
||||
../cmd/godoc\
|
||||
../cmd/goinstall\
|
||||
../cmd/gotest\
|
||||
../cmd/goyacc\
|
||||
../cmd/hgpatch\
|
||||
|
Loading…
Reference in New Issue
Block a user