// Copyright 2013 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 ( "bytes" "encoding/json" "encoding/xml" "flag" "fmt" "io/ioutil" "net/http" "net/url" "os" "os/exec" "strings" ) var ( builder = flag.String("builder", "", "builder name") key = flag.String("key", "", "builder key") gopath = flag.String("gopath", "", "path to go repo") dashboard = flag.String("dashboard", "build.golang.org", "Go Dashboard Host") batch = flag.Int("batch", 100, "upload batch size") ) // Do not benchmark beyond this commit. // There is little sense in benchmarking till first commit, // and the benchmark won't build anyway. const Go1Commit = "0051c7442fed" // test/bench/shootout: update timing.log to Go 1. // HgLog represents a single Mercurial revision. type HgLog struct { Hash string Branch string Files string } func main() { flag.Parse() logs := hgLog() var hashes []string ngo1 := 0 for i := range logs { if strings.HasPrefix(logs[i].Hash, Go1Commit) { break } if needsBenchmarking(&logs[i]) { hashes = append(hashes, logs[i].Hash) } ngo1++ } fmt.Printf("found %v commits, %v after Go1, %v need benchmarking\n", len(logs), ngo1, len(hashes)) for i := 0; i < len(hashes); i += *batch { j := i + *batch if j > len(hashes) { j = len(hashes) } fmt.Printf("sending %v-%v... ", i, j) res := postCommits(hashes[i:j]) fmt.Printf("%s\n", res) } } func hgLog() []HgLog { var out bytes.Buffer cmd := exec.Command("hg", "log", "--encoding=utf-8", "--template", xmlLogTemplate) cmd.Dir = *gopath cmd.Stdout = &out cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { fmt.Printf("failed to execute 'hg log': %v\n", err) os.Exit(1) } var top struct{ Log []HgLog } err = xml.Unmarshal([]byte(""+out.String()+""), &top) if err != nil { fmt.Printf("failed to parse log: %v\n", err) os.Exit(1) } return top.Log } func needsBenchmarking(log *HgLog) bool { if log.Branch != "" { return false } for _, f := range strings.Split(log.Files, " ") { if (strings.HasPrefix(f, "include") || strings.HasPrefix(f, "src")) && !strings.HasSuffix(f, "_test.go") && !strings.Contains(f, "testdata") { return true } } return false } func postCommits(hashes []string) string { args := url.Values{"builder": {*builder}, "key": {*key}} cmd := fmt.Sprintf("http://%v/updatebenchmark?%v", *dashboard, args.Encode()) b, err := json.Marshal(hashes) if err != nil { return fmt.Sprintf("failed to encode request: %v\n", err) } r, err := http.Post(cmd, "text/json", bytes.NewReader(b)) if err != nil { return fmt.Sprintf("failed to send http request: %v\n", err) } defer r.Body.Close() if r.StatusCode != http.StatusOK { return fmt.Sprintf("http request failed: %v\n", r.Status) } resp, err := ioutil.ReadAll(r.Body) if err != nil { return fmt.Sprintf("failed to read http response: %v\n", err) } return string(resp) } const xmlLogTemplate = ` {node|escape} {branches} {files} `