Compare commits
15 Commits
master
...
release-br
Author | SHA1 | Date |
---|---|---|
|
e7e52e73e2 | |
|
156d532d4f | |
|
8cc6a32d9b | |
|
0d7f9d6ece | |
|
be728107ea | |
|
d1fff0794f | |
|
42933c415e | |
|
e9928cbe4a | |
|
d3e4ceb59d | |
|
97530abbb5 | |
|
bd7f39a7ac | |
|
27eedfbdea | |
|
1396c68d3b | |
|
c1ca329f65 | |
|
4c772e4117 |
|
@ -154,19 +154,32 @@ func waitForServerReady(t *testing.T, addr string) {
|
||||||
waitForServer(t,
|
waitForServer(t,
|
||||||
fmt.Sprintf("http://%v/", addr),
|
fmt.Sprintf("http://%v/", addr),
|
||||||
"The Go Programming Language",
|
"The Go Programming Language",
|
||||||
15*time.Second)
|
15*time.Second,
|
||||||
|
false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitForSearchReady(t *testing.T, addr string) {
|
func waitForSearchReady(t *testing.T, addr string) {
|
||||||
waitForServer(t,
|
waitForServer(t,
|
||||||
fmt.Sprintf("http://%v/search?q=FALLTHROUGH", addr),
|
fmt.Sprintf("http://%v/search?q=FALLTHROUGH", addr),
|
||||||
"The list of tokens.",
|
"The list of tokens.",
|
||||||
2*time.Minute)
|
2*time.Minute,
|
||||||
|
false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitUntilScanComplete(t *testing.T, addr string) {
|
||||||
|
waitForServer(t,
|
||||||
|
fmt.Sprintf("http://%v/pkg", addr),
|
||||||
|
"Scan is not yet complete",
|
||||||
|
2*time.Minute,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
// setting reverse as true, which means this waits
|
||||||
|
// until the string is not returned in the response anymore
|
||||||
}
|
}
|
||||||
|
|
||||||
const pollInterval = 200 * time.Millisecond
|
const pollInterval = 200 * time.Millisecond
|
||||||
|
|
||||||
func waitForServer(t *testing.T, url, match string, timeout time.Duration) {
|
func waitForServer(t *testing.T, url, match string, timeout time.Duration, reverse bool) {
|
||||||
// "health check" duplicated from x/tools/cmd/tipgodoc/tip.go
|
// "health check" duplicated from x/tools/cmd/tipgodoc/tip.go
|
||||||
deadline := time.Now().Add(timeout)
|
deadline := time.Now().Add(timeout)
|
||||||
for time.Now().Before(deadline) {
|
for time.Now().Before(deadline) {
|
||||||
|
@ -177,9 +190,13 @@ func waitForServer(t *testing.T, url, match string, timeout time.Duration) {
|
||||||
}
|
}
|
||||||
rbody, err := ioutil.ReadAll(res.Body)
|
rbody, err := ioutil.ReadAll(res.Body)
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
if err == nil && res.StatusCode == http.StatusOK &&
|
if err == nil && res.StatusCode == http.StatusOK {
|
||||||
bytes.Contains(rbody, []byte(match)) {
|
if bytes.Contains(rbody, []byte(match)) && !reverse {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
if !bytes.Contains(rbody, []byte(match)) && reverse {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Fatalf("Server failed to respond in %v", timeout)
|
t.Fatalf("Server failed to respond in %v", timeout)
|
||||||
|
@ -219,7 +236,12 @@ func testWeb(t *testing.T, withIndex bool) {
|
||||||
cmd.Stdout = os.Stderr
|
cmd.Stdout = os.Stderr
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Args[0] = "godoc"
|
cmd.Args[0] = "godoc"
|
||||||
cmd.Env = godocEnv()
|
|
||||||
|
// Set GOPATH variable to non-existing path.
|
||||||
|
// We cannot just unset GOPATH variable because godoc would default it to ~/go.
|
||||||
|
// (We don't want the indexer looking at the local workspace during tests.)
|
||||||
|
cmd.Env = append(os.Environ(), "GOPATH=does_not_exist")
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
t.Fatalf("failed to start godoc: %s", err)
|
t.Fatalf("failed to start godoc: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -229,6 +251,7 @@ func testWeb(t *testing.T, withIndex bool) {
|
||||||
waitForSearchReady(t, addr)
|
waitForSearchReady(t, addr)
|
||||||
} else {
|
} else {
|
||||||
waitForServerReady(t, addr)
|
waitForServerReady(t, addr)
|
||||||
|
waitUntilScanComplete(t, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@ -372,14 +395,9 @@ func main() { print(lib.V) }
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
addr := serverAddress(t)
|
addr := serverAddress(t)
|
||||||
cmd := exec.Command(bin, fmt.Sprintf("-http=%s", addr), "-analysis=type")
|
cmd := exec.Command(bin, fmt.Sprintf("-http=%s", addr), "-analysis=type")
|
||||||
|
cmd.Env = os.Environ()
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GOROOT=%s", filepath.Join(tmpdir, "goroot")))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GOROOT=%s", filepath.Join(tmpdir, "goroot")))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GOPATH=%s", filepath.Join(tmpdir, "gopath")))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GOPATH=%s", filepath.Join(tmpdir, "gopath")))
|
||||||
for _, e := range os.Environ() {
|
|
||||||
if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cmd.Env = append(cmd.Env, e)
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stderr
|
cmd.Stdout = os.Stderr
|
||||||
stderr, err := cmd.StderrPipe()
|
stderr, err := cmd.StderrPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -457,15 +475,3 @@ tryagain:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// godocEnv returns the process environment without the GOPATH variable.
|
|
||||||
// (We don't want the indexer looking at the local workspace during tests.)
|
|
||||||
func godocEnv() (env []string) {
|
|
||||||
for _, v := range os.Environ() {
|
|
||||||
if strings.HasPrefix(v, "GOPATH=") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
env = append(env, v)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
|
@ -333,7 +333,7 @@ func main() {
|
||||||
|
|
||||||
// Start http server.
|
// Start http server.
|
||||||
if *verbose {
|
if *verbose {
|
||||||
log.Println("starting http server")
|
log.Println("starting HTTP server")
|
||||||
}
|
}
|
||||||
if err := http.ListenAndServe(*httpAddr, handler); err != nil {
|
if err := http.ListenAndServe(*httpAddr, handler); err != nil {
|
||||||
log.Fatalf("ListenAndServe %s: %v", *httpAddr, err)
|
log.Fatalf("ListenAndServe %s: %v", *httpAddr, err)
|
||||||
|
|
|
@ -32,6 +32,7 @@ var xMap = map[string]xRepo{
|
||||||
"debug": {"https://go.googlesource.com/debug", "git"},
|
"debug": {"https://go.googlesource.com/debug", "git"},
|
||||||
"exp": {"https://go.googlesource.com/exp", "git"},
|
"exp": {"https://go.googlesource.com/exp", "git"},
|
||||||
"image": {"https://go.googlesource.com/image", "git"},
|
"image": {"https://go.googlesource.com/image", "git"},
|
||||||
|
"lint": {"https://go.googlesource.com/lint", "git"},
|
||||||
"mobile": {"https://go.googlesource.com/mobile", "git"},
|
"mobile": {"https://go.googlesource.com/mobile", "git"},
|
||||||
"net": {"https://go.googlesource.com/net", "git"},
|
"net": {"https://go.googlesource.com/net", "git"},
|
||||||
"oauth2": {"https://go.googlesource.com/oauth2", "git"},
|
"oauth2": {"https://go.googlesource.com/oauth2", "git"},
|
||||||
|
@ -46,6 +47,7 @@ var xMap = map[string]xRepo{
|
||||||
"time": {"https://go.googlesource.com/time", "git"},
|
"time": {"https://go.googlesource.com/time", "git"},
|
||||||
"tools": {"https://go.googlesource.com/tools", "git"},
|
"tools": {"https://go.googlesource.com/tools", "git"},
|
||||||
"tour": {"https://go.googlesource.com/tour", "git"},
|
"tour": {"https://go.googlesource.com/tour", "git"},
|
||||||
|
"vgo": {"https://go.googlesource.com/vgo", "git"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -56,5 +56,5 @@ references to field f int
|
||||||
|
|
||||||
-------- @referrers ref-type-U --------
|
-------- @referrers ref-type-U --------
|
||||||
references to type U int
|
references to type U int
|
||||||
open testdata/src/referrers/nosuchfile.y: no such file or directory (+ 1 more refs in this file)
|
open nosuchfile.y: no such file or directory (+ 1 more refs in this file)
|
||||||
|
|
||||||
|
|
100
godoc/dl/dl.go
100
godoc/dl/dl.go
|
@ -16,6 +16,7 @@ import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -27,7 +28,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
"google.golang.org/appengine"
|
"google.golang.org/appengine"
|
||||||
"google.golang.org/appengine/datastore"
|
"google.golang.org/appengine/datastore"
|
||||||
"google.golang.org/appengine/log"
|
"google.golang.org/appengine/log"
|
||||||
|
@ -41,22 +41,24 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterHandlers(mux *http.ServeMux) {
|
func RegisterHandlers(mux *http.ServeMux) {
|
||||||
mux.Handle("/dl", http.RedirectHandler("/dl/", http.StatusFound))
|
mux.HandleFunc("/dl", getHandler)
|
||||||
mux.HandleFunc("/dl/", getHandler) // also serves listHandler
|
mux.HandleFunc("/dl/", getHandler) // also serves listHandler
|
||||||
mux.HandleFunc("/dl/upload", uploadHandler)
|
mux.HandleFunc("/dl/upload", uploadHandler)
|
||||||
mux.HandleFunc("/dl/init", initHandler)
|
mux.HandleFunc("/dl/init", initHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File represents a file on the golang.org downloads page.
|
||||||
|
// It should be kept in sync with the upload code in x/build/cmd/release.
|
||||||
type File struct {
|
type File struct {
|
||||||
Filename string
|
Filename string `json:"filename"`
|
||||||
OS string
|
OS string `json:"os"`
|
||||||
Arch string
|
Arch string `json:"arch"`
|
||||||
Version string
|
Version string `json:"version"`
|
||||||
Checksum string `datastore:",noindex"` // SHA1; deprecated
|
Checksum string `json:"-" datastore:",noindex"` // SHA1; deprecated
|
||||||
ChecksumSHA256 string `datastore:",noindex"`
|
ChecksumSHA256 string `json:"sha256" datastore:",noindex"`
|
||||||
Size int64 `datastore:",noindex"`
|
Size int64 `json:"size" datastore:",noindex"`
|
||||||
Kind string // "archive", "installer", "source"
|
Kind string `json:"kind"` // "archive", "installer", "source"
|
||||||
Uploaded time.Time
|
Uploaded time.Time `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f File) ChecksumType() string {
|
func (f File) ChecksumType() string {
|
||||||
|
@ -137,11 +139,11 @@ func (f File) URL() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Release struct {
|
type Release struct {
|
||||||
Version string
|
Version string `json:"version"`
|
||||||
Stable bool
|
Stable bool `json:"stable"`
|
||||||
Files []File
|
Files []File `json:"files"`
|
||||||
Visible bool // show files on page load
|
Visible bool `json:"-"` // show files on page load
|
||||||
SplitPortTable bool // whether files should be split by primary/other ports.
|
SplitPortTable bool `json:"-"` // whether files should be split by primary/other ports.
|
||||||
}
|
}
|
||||||
|
|
||||||
type Feature struct {
|
type Feature struct {
|
||||||
|
@ -159,12 +161,12 @@ type Feature struct {
|
||||||
var featuredFiles = []Feature{
|
var featuredFiles = []Feature{
|
||||||
{
|
{
|
||||||
Platform: "Microsoft Windows",
|
Platform: "Microsoft Windows",
|
||||||
Requirements: "Windows XP SP3 or later, Intel 64-bit processor",
|
Requirements: "Windows 7 or later, Intel 64-bit processor",
|
||||||
fileRE: regexp.MustCompile(`\.windows-amd64\.msi$`),
|
fileRE: regexp.MustCompile(`\.windows-amd64\.msi$`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Platform: "Apple macOS",
|
Platform: "Apple macOS",
|
||||||
Requirements: "macOS 10.8 or later, Intel 64-bit processor",
|
Requirements: "macOS 10.10 or later, Intel 64-bit processor",
|
||||||
fileRE: regexp.MustCompile(`\.darwin-amd64(-osx10\.8)?\.pkg$`),
|
fileRE: regexp.MustCompile(`\.darwin-amd64(-osx10\.8)?\.pkg$`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -221,6 +223,17 @@ func listHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Errorf(c, "cache set error: %v", err)
|
log.Errorf(c, "cache set error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.URL.Query().Get("mode") == "json" {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
if err := enc.Encode(d.Stable); err != nil {
|
||||||
|
log.Errorf(c, "failed rendering JSON for releases: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := listTemplate.ExecuteTemplate(w, "root", d); err != nil {
|
if err := listTemplate.ExecuteTemplate(w, "root", d); err != nil {
|
||||||
log.Errorf(c, "error executing template: %v", err)
|
log.Errorf(c, "error executing template: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -415,21 +428,59 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHandler(w http.ResponseWriter, r *http.Request) {
|
func getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// For go get golang.org/dl/go1.x.y, we need to serve the
|
||||||
|
// same meta tags at /dl for cmd/go to validate against /dl/go1.x.y:
|
||||||
|
if r.URL.Path == "/dl" && (r.Method == "GET" || r.Method == "HEAD") && r.FormValue("go-get") == "1" {
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
fmt.Fprintf(w, `<!DOCTYPE html><html><head>
|
||||||
|
<meta name="go-import" content="golang.org/dl git https://go.googlesource.com/dl">
|
||||||
|
</head></html>`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.URL.Path == "/dl" {
|
||||||
|
http.Redirect(w, r, "/dl/", http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
name := strings.TrimPrefix(r.URL.Path, "/dl/")
|
name := strings.TrimPrefix(r.URL.Path, "/dl/")
|
||||||
if name == "" {
|
if name == "" {
|
||||||
listHandler(w, r)
|
listHandler(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !fileRe.MatchString(name) {
|
if fileRe.MatchString(name) {
|
||||||
http.NotFound(w, r)
|
http.Redirect(w, r, downloadBaseURL+name, http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, downloadBaseURL+name, http.StatusFound)
|
if goGetRe.MatchString(name) {
|
||||||
|
var isGoGet bool
|
||||||
|
if r.Method == "GET" || r.Method == "HEAD" {
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
isGoGet = r.FormValue("go-get") == "1"
|
||||||
|
}
|
||||||
|
if !isGoGet {
|
||||||
|
w.Header().Set("Location", "https://golang.org/dl/#"+name)
|
||||||
|
w.WriteHeader(http.StatusFound)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, `<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
|
<meta name="go-import" content="golang.org/dl git https://go.googlesource.com/dl">
|
||||||
|
<meta http-equiv="refresh" content="0; url=https://golang.org/dl/#%s">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Nothing to see here; <a href="https://golang.org/dl/#%s">move along</a>.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`, html.EscapeString(name), html.EscapeString(name))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validUser(user string) bool {
|
func validUser(user string) bool {
|
||||||
switch user {
|
switch user {
|
||||||
case "adg", "bradfitz", "cbro", "andybons":
|
case "adg", "bradfitz", "cbro", "andybons", "valsorda":
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -441,7 +492,10 @@ func userKey(c context.Context, user string) string {
|
||||||
return fmt.Sprintf("%x", h.Sum(nil))
|
return fmt.Sprintf("%x", h.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileRe = regexp.MustCompile(`^go[0-9a-z.]+\.[0-9a-z.-]+\.(tar\.gz|pkg|msi|zip)$`)
|
var (
|
||||||
|
fileRe = regexp.MustCompile(`^go[0-9a-z.]+\.[0-9a-z.-]+\.(tar\.gz|pkg|msi|zip)$`)
|
||||||
|
goGetRe = regexp.MustCompile(`^go[0-9a-z.]+\.[0-9a-z.-]+$`)
|
||||||
|
)
|
||||||
|
|
||||||
func initHandler(w http.ResponseWriter, r *http.Request) {
|
func initHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var fileRoot struct {
|
var fileRoot struct {
|
||||||
|
|
|
@ -220,7 +220,7 @@ $(document).ready(function() {
|
||||||
<p>This is an <b>unstable</b> version of Go. Use with caution.</p>
|
<p>This is an <b>unstable</b> version of Go. Use with caution.</p>
|
||||||
<p>If you already have Go installed, you can install this version by running:</p>
|
<p>If you already have Go installed, you can install this version by running:</p>
|
||||||
<pre>
|
<pre>
|
||||||
go get golang.org/x/build/version/{{.Version}}
|
go get golang.org/dl/{{.Version}}
|
||||||
</pre>
|
</pre>
|
||||||
<p>Then, use the <code>{{.Version}}</code> command instead of the <code>go</code> command to use {{.Version}}.</p>
|
<p>Then, use the <code>{{.Version}}</code> command instead of the <code>go</code> command to use {{.Version}}.</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -253,13 +253,13 @@ function personalizeInstallInstructions() {
|
||||||
|
|
||||||
var filename = s.substr(prefix.length);
|
var filename = s.substr(prefix.length);
|
||||||
var filenameRE = /^go1\.\d+(\.\d+)?([a-z0-9]+)?\.([a-z0-9]+)(-[a-z0-9]+)?(-osx10\.[68])?\.([a-z.]+)$/;
|
var filenameRE = /^go1\.\d+(\.\d+)?([a-z0-9]+)?\.([a-z0-9]+)(-[a-z0-9]+)?(-osx10\.[68])?\.([a-z.]+)$/;
|
||||||
$('.downloadFilename').text(filename);
|
|
||||||
$('.hideFromDownload').hide();
|
|
||||||
var m = filenameRE.exec(filename);
|
var m = filenameRE.exec(filename);
|
||||||
if (!m) {
|
if (!m) {
|
||||||
// Can't interpret file name; bail.
|
// Can't interpret file name; bail.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$('.downloadFilename').text(filename);
|
||||||
|
$('.hideFromDownload').hide();
|
||||||
|
|
||||||
var os = m[3];
|
var os = m[3];
|
||||||
var ext = m[6];
|
var ext = m[6];
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -90,7 +90,7 @@ func (p *Presentation) code(file string, arg ...interface{}) (s string, err erro
|
||||||
command = fmt.Sprintf("code %q %s %s", file, stringFor(arg[0]), stringFor(arg[1]))
|
command = fmt.Sprintf("code %q %s %s", file, stringFor(arg[0]), stringFor(arg[1]))
|
||||||
text = p.Corpus.multipleLines(file, text, arg[0], arg[1])
|
text = p.Corpus.multipleLines(file, text, arg[0], arg[1])
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("incorrect code invocation: code %q %q", file, arg)
|
return "", fmt.Errorf("incorrect code invocation: code %q [%v, ...] (%d arguments)", file, arg[0], len(arg))
|
||||||
}
|
}
|
||||||
// Trim spaces from output.
|
// Trim spaces from output.
|
||||||
text = strings.Trim(text, "\n")
|
text = strings.Trim(text, "\n")
|
||||||
|
|
Loading…
Reference in New Issue