summaryrefslogtreecommitdiff
path: root/misc/dashboard/builder
diff options
context:
space:
mode:
Diffstat (limited to 'misc/dashboard/builder')
-rw-r--r--misc/dashboard/builder/Makefile14
-rw-r--r--misc/dashboard/builder/doc.go58
-rw-r--r--misc/dashboard/builder/exec.go74
-rw-r--r--misc/dashboard/builder/http.go147
-rw-r--r--misc/dashboard/builder/main.go624
-rw-r--r--misc/dashboard/builder/package.go94
6 files changed, 0 insertions, 1011 deletions
diff --git a/misc/dashboard/builder/Makefile b/misc/dashboard/builder/Makefile
deleted file mode 100644
index f1d9c5497..000000000
--- a/misc/dashboard/builder/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2009 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.
-
-include ../../../src/Make.inc
-
-TARG=gobuilder
-GOFILES=\
- exec.go\
- http.go\
- main.go\
- package.go\
-
-include ../../../src/Make.cmd
diff --git a/misc/dashboard/builder/doc.go b/misc/dashboard/builder/doc.go
deleted file mode 100644
index 30d8fe948..000000000
--- a/misc/dashboard/builder/doc.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2010 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.
-
-/*
-
-Go Builder is a continuous build client for the Go project.
-It integrates with the Go Dashboard AppEngine application.
-
-Go Builder is intended to run continuously as a background process.
-
-It periodically pulls updates from the Go Mercurial repository.
-
-When a newer revision is found, Go Builder creates a clone of the repository,
-runs all.bash, and reports build success or failure to the Go Dashboard.
-
-For a release revision (a change description that matches "release.YYYY-MM-DD"),
-Go Builder will create a tar.gz archive of the GOROOT and deliver it to the
-Go Google Code project's downloads section.
-
-Usage:
-
- gobuilder goos-goarch...
-
- Several goos-goarch combinations can be provided, and the builder will
- build them in serial.
-
-Optional flags:
-
- -dashboard="godashboard.appspot.com": Go Dashboard Host
- The location of the Go Dashboard application to which Go Builder will
- report its results.
-
- -release: Build and deliver binary release archive
-
- -rev=N: Build revision N and exit
-
- -cmd="./all.bash": Build command (specify absolute or relative to go/src)
-
- -v: Verbose logging
-
- -external: External package builder mode (will not report Go build
- state to dashboard or issue releases)
-
-The key file should be located at $HOME/.gobuildkey or, for a builder-specific
-key, $HOME/.gobuildkey-$BUILDER (eg, $HOME/.gobuildkey-linux-amd64).
-
-The build key file is a text file of the format:
-
- godashboard-key
- googlecode-username
- googlecode-password
-
-If the Google Code credentials are not provided the archival step
-will be skipped.
-
-*/
-package documentation
diff --git a/misc/dashboard/builder/exec.go b/misc/dashboard/builder/exec.go
deleted file mode 100644
index a042c5699..000000000
--- a/misc/dashboard/builder/exec.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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 (
- "bytes"
- "exec"
- "io"
- "log"
- "os"
- "strings"
-)
-
-// run is a simple wrapper for exec.Run/Close
-func run(envv []string, dir string, argv ...string) os.Error {
- if *verbose {
- log.Println("run", argv)
- }
- argv = useBash(argv)
- cmd := exec.Command(argv[0], argv[1:]...)
- cmd.Dir = dir
- cmd.Env = envv
- cmd.Stderr = os.Stderr
- return cmd.Run()
-}
-
-// runLog runs a process and returns the combined stdout/stderr,
-// as well as writing it to logfile (if specified). It returns
-// process combined stdout and stderr output, exit status and error.
-// The error returned is nil, if process is started successfully,
-// even if exit status is not 0.
-func runLog(envv []string, logfile, dir string, argv ...string) (string, int, os.Error) {
- if *verbose {
- log.Println("runLog", argv)
- }
- argv = useBash(argv)
-
- b := new(bytes.Buffer)
- var w io.Writer = b
- if logfile != "" {
- f, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
- if err != nil {
- return "", 0, err
- }
- defer f.Close()
- w = io.MultiWriter(f, b)
- }
-
- cmd := exec.Command(argv[0], argv[1:]...)
- cmd.Dir = dir
- cmd.Env = envv
- cmd.Stdout = w
- cmd.Stderr = w
-
- err := cmd.Run()
- if err != nil {
- if ws, ok := err.(*os.Waitmsg); ok {
- return b.String(), ws.ExitStatus(), nil
- }
- }
- return b.String(), 0, nil
-}
-
-// useBash prefixes a list of args with 'bash' if the first argument
-// is a bash script.
-func useBash(argv []string) []string {
- // TODO(brainman): choose a more reliable heuristic here.
- if strings.HasSuffix(argv[0], ".bash") {
- argv = append([]string{"bash"}, argv...)
- }
- return argv
-}
diff --git a/misc/dashboard/builder/http.go b/misc/dashboard/builder/http.go
deleted file mode 100644
index 98400c51a..000000000
--- a/misc/dashboard/builder/http.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// 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 (
- "bytes"
- "fmt"
- "http"
- "json"
- "log"
- "os"
- "strconv"
-)
-
-type param map[string]string
-
-// dash runs the given method and command on the dashboard.
-// If args is not nil, it is the query or post parameters.
-// If resp is not nil, dash unmarshals the body as JSON into resp.
-func dash(meth, cmd string, resp interface{}, args param) os.Error {
- var r *http.Response
- var err os.Error
- if *verbose {
- log.Println("dash", cmd, args)
- }
- cmd = "http://" + *dashboard + "/" + cmd
- vals := make(http.Values)
- for k, v := range args {
- vals.Add(k, v)
- }
- switch meth {
- case "GET":
- if q := vals.Encode(); q != "" {
- cmd += "?" + q
- }
- r, err = http.Get(cmd)
- case "POST":
- r, err = http.PostForm(cmd, vals)
- default:
- return fmt.Errorf("unknown method %q", meth)
- }
- if err != nil {
- return err
- }
- defer r.Body.Close()
- var buf bytes.Buffer
- buf.ReadFrom(r.Body)
- if resp != nil {
- if err = json.Unmarshal(buf.Bytes(), resp); err != nil {
- log.Printf("json unmarshal %#q: %s\n", buf.Bytes(), err)
- return err
- }
- }
- return nil
-}
-
-func dashStatus(meth, cmd string, args param) os.Error {
- var resp struct {
- Status string
- Error string
- }
- err := dash(meth, cmd, &resp, args)
- if err != nil {
- return err
- }
- if resp.Status != "OK" {
- return os.NewError("/build: " + resp.Error)
- }
- return nil
-}
-
-// todo returns the next hash to build.
-func (b *Builder) todo() (rev string, err os.Error) {
- var resp []struct {
- Hash string
- }
- if err = dash("GET", "todo", &resp, param{"builder": b.name}); err != nil {
- return
- }
- if len(resp) > 0 {
- rev = resp[0].Hash
- }
- return
-}
-
-// recordResult sends build results to the dashboard
-func (b *Builder) recordResult(buildLog string, hash string) os.Error {
- return dash("POST", "build", nil, param{
- "builder": b.name,
- "key": b.key,
- "node": hash,
- "log": buildLog,
- })
-}
-
-// packages fetches a list of package paths from the dashboard
-func packages() (pkgs []string, err os.Error) {
- var resp struct {
- Packages []struct {
- Path string
- }
- }
- err = dash("GET", "package", &resp, param{"fmt": "json"})
- if err != nil {
- return
- }
- for _, p := range resp.Packages {
- pkgs = append(pkgs, p.Path)
- }
- return
-}
-
-// updatePackage sends package build results and info dashboard
-func (b *Builder) updatePackage(pkg string, ok bool, buildLog, info string) os.Error {
- return dash("POST", "package", nil, param{
- "builder": b.name,
- "key": b.key,
- "path": pkg,
- "ok": strconv.Btoa(ok),
- "log": buildLog,
- "info": info,
- })
-}
-
-// postCommit informs the dashboard of a new commit
-func postCommit(key string, l *HgLog) os.Error {
- return dashStatus("POST", "commit", param{
- "key": key,
- "node": l.Hash,
- "date": l.Date,
- "user": l.Author,
- "parent": l.Parent,
- "desc": l.Desc,
- })
-}
-
-// dashboardCommit returns true if the dashboard knows about hash.
-func dashboardCommit(hash string) bool {
- err := dashStatus("GET", "commit", param{"node": hash})
- if err != nil {
- log.Printf("check %s: %s", hash, err)
- return false
- }
- return true
-}
diff --git a/misc/dashboard/builder/main.go b/misc/dashboard/builder/main.go
deleted file mode 100644
index 989965bc4..000000000
--- a/misc/dashboard/builder/main.go
+++ /dev/null
@@ -1,624 +0,0 @@
-// 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 (
- "flag"
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "path"
- "regexp"
- "runtime"
- "strconv"
- "strings"
- "time"
- "xml"
-)
-
-const (
- codeProject = "go"
- codePyScript = "misc/dashboard/googlecode_upload.py"
- hgUrl = "https://go.googlecode.com/hg/"
- waitInterval = 30e9 // time to wait before checking for new revs
- mkdirPerm = 0750
- pkgBuildInterval = 1e9 * 60 * 60 * 24 // rebuild packages every 24 hours
-)
-
-// These variables are copied from the gobuilder's environment
-// to the envv of its subprocesses.
-var extraEnv = []string{
- "GOHOSTOS",
- "GOHOSTARCH",
- "PATH",
- "DISABLE_NET_TESTS",
- "MAKEFLAGS",
- "GOARM",
-}
-
-type Builder struct {
- name string
- goos, goarch string
- key string
- codeUsername string
- codePassword string
-}
-
-var (
- buildroot = flag.String("buildroot", path.Join(os.TempDir(), "gobuilder"), "Directory under which to build")
- commitFlag = flag.Bool("commit", false, "upload information about new commits")
- dashboard = flag.String("dashboard", "godashboard.appspot.com", "Go Dashboard Host")
- buildRelease = flag.Bool("release", false, "Build and upload binary release archives")
- buildRevision = flag.String("rev", "", "Build specified revision and exit")
- buildCmd = flag.String("cmd", "./all.bash", "Build command (specify absolute or relative to go/src/)")
- external = flag.Bool("external", false, "Build external packages")
- parallel = flag.Bool("parallel", false, "Build multiple targets in parallel")
- verbose = flag.Bool("v", false, "verbose")
-)
-
-var (
- goroot string
- binaryTagRe = regexp.MustCompile(`^(release\.r|weekly\.)[0-9\-.]+`)
- releaseRe = regexp.MustCompile(`^release\.r[0-9\-.]+`)
-)
-
-func main() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "usage: %s goos-goarch...\n", os.Args[0])
- flag.PrintDefaults()
- os.Exit(2)
- }
- flag.Parse()
- if len(flag.Args()) == 0 && !*commitFlag {
- flag.Usage()
- }
- goroot = path.Join(*buildroot, "goroot")
- builders := make([]*Builder, len(flag.Args()))
- for i, builder := range flag.Args() {
- b, err := NewBuilder(builder)
- if err != nil {
- log.Fatal(err)
- }
- builders[i] = b
- }
-
- // set up work environment
- if err := os.RemoveAll(*buildroot); err != nil {
- log.Fatalf("Error removing build root (%s): %s", *buildroot, err)
- }
- if err := os.Mkdir(*buildroot, mkdirPerm); err != nil {
- log.Fatalf("Error making build root (%s): %s", *buildroot, err)
- }
- if err := run(nil, *buildroot, "hg", "clone", hgUrl, goroot); err != nil {
- log.Fatal("Error cloning repository:", err)
- }
-
- if *commitFlag {
- if len(flag.Args()) == 0 {
- commitWatcher()
- return
- }
- go commitWatcher()
- }
-
- // if specified, build revision and return
- if *buildRevision != "" {
- hash, err := fullHash(*buildRevision)
- if err != nil {
- log.Fatal("Error finding revision: ", err)
- }
- for _, b := range builders {
- if err := b.buildHash(hash); err != nil {
- log.Println(err)
- }
- }
- return
- }
-
- // external package build mode
- if *external {
- if len(builders) != 1 {
- log.Fatal("only one goos-goarch should be specified with -external")
- }
- builders[0].buildExternal()
- }
-
- // go continuous build mode (default)
- // check for new commits and build them
- for {
- built := false
- t := time.Nanoseconds()
- if *parallel {
- done := make(chan bool)
- for _, b := range builders {
- go func(b *Builder) {
- done <- b.build()
- }(b)
- }
- for _ = range builders {
- built = <-done || built
- }
- } else {
- for _, b := range builders {
- built = b.build() || built
- }
- }
- // sleep if there was nothing to build
- if !built {
- time.Sleep(waitInterval)
- }
- // sleep if we're looping too fast.
- t1 := time.Nanoseconds() - t
- if t1 < waitInterval {
- time.Sleep(waitInterval - t1)
- }
- }
-}
-
-func NewBuilder(builder string) (*Builder, os.Error) {
- b := &Builder{name: builder}
-
- // get goos/goarch from builder string
- s := strings.SplitN(builder, "-", 3)
- if len(s) >= 2 {
- b.goos, b.goarch = s[0], s[1]
- } else {
- return nil, fmt.Errorf("unsupported builder form: %s", builder)
- }
-
- // read keys from keyfile
- fn := path.Join(os.Getenv("HOME"), ".gobuildkey")
- if s := fn + "-" + b.name; isFile(s) { // builder-specific file
- fn = s
- }
- c, err := ioutil.ReadFile(fn)
- if err != nil {
- return nil, fmt.Errorf("readKeys %s (%s): %s", b.name, fn, err)
- }
- v := strings.Split(string(c), "\n")
- b.key = v[0]
- if len(v) >= 3 {
- b.codeUsername, b.codePassword = v[1], v[2]
- }
-
- return b, nil
-}
-
-// buildExternal downloads and builds external packages, and
-// reports their build status to the dashboard.
-// It will re-build all packages after pkgBuildInterval nanoseconds or
-// a new release tag is found.
-func (b *Builder) buildExternal() {
- var prevTag string
- var nextBuild int64
- for {
- time.Sleep(waitInterval)
- err := run(nil, goroot, "hg", "pull", "-u")
- if err != nil {
- log.Println("hg pull failed:", err)
- continue
- }
- hash, tag, err := firstTag(releaseRe)
- if err != nil {
- log.Println(err)
- continue
- }
- if *verbose {
- log.Println("latest release:", tag)
- }
- // don't rebuild if there's no new release
- // and it's been less than pkgBuildInterval
- // nanoseconds since the last build.
- if tag == prevTag && time.Nanoseconds() < nextBuild {
- continue
- }
- // build will also build the packages
- if err := b.buildHash(hash); err != nil {
- log.Println(err)
- continue
- }
- prevTag = tag
- nextBuild = time.Nanoseconds() + pkgBuildInterval
- }
-}
-
-// build checks for a new commit for this builder
-// and builds it if one is found.
-// It returns true if a build was attempted.
-func (b *Builder) build() bool {
- defer func() {
- err := recover()
- if err != nil {
- log.Println(b.name, "build:", err)
- }
- }()
- hash, err := b.todo()
- if err != nil {
- log.Println(err)
- return false
- }
- if hash == "" {
- return false
- }
- // Look for hash locally before running hg pull.
-
- if _, err := fullHash(hash[:12]); err != nil {
- // Don't have hash, so run hg pull.
- if err := run(nil, goroot, "hg", "pull"); err != nil {
- log.Println("hg pull failed:", err)
- return false
- }
- }
- err = b.buildHash(hash)
- if err != nil {
- log.Println(err)
- }
- return true
-}
-
-func (b *Builder) buildHash(hash string) (err os.Error) {
- defer func() {
- if err != nil {
- err = fmt.Errorf("%s build: %s: %s", b.name, hash, err)
- }
- }()
-
- log.Println(b.name, "building", hash)
-
- // create place in which to do work
- workpath := path.Join(*buildroot, b.name+"-"+hash[:12])
- err = os.Mkdir(workpath, mkdirPerm)
- if err != nil {
- return
- }
- defer os.RemoveAll(workpath)
-
- // clone repo
- err = run(nil, workpath, "hg", "clone", goroot, "go")
- if err != nil {
- return
- }
-
- // update to specified revision
- err = run(nil, path.Join(workpath, "go"),
- "hg", "update", hash)
- if err != nil {
- return
- }
-
- srcDir := path.Join(workpath, "go", "src")
-
- // build
- logfile := path.Join(workpath, "build.log")
- buildLog, status, err := runLog(b.envv(), logfile, srcDir, *buildCmd)
- if err != nil {
- return fmt.Errorf("%s: %s", *buildCmd, err)
- }
-
- // if we're in external mode, build all packages and return
- if *external {
- if status != 0 {
- return os.NewError("go build failed")
- }
- return b.buildPackages(workpath, hash)
- }
-
- if status != 0 {
- // record failure
- return b.recordResult(buildLog, hash)
- }
-
- // record success
- if err = b.recordResult("", hash); err != nil {
- return fmt.Errorf("recordResult: %s", err)
- }
-
- // finish here if codeUsername and codePassword aren't set
- if b.codeUsername == "" || b.codePassword == "" || !*buildRelease {
- return
- }
-
- // if this is a release, create tgz and upload to google code
- releaseHash, release, err := firstTag(binaryTagRe)
- if hash == releaseHash {
- // clean out build state
- err = run(b.envv(), srcDir, "./clean.bash", "--nopkg")
- if err != nil {
- return fmt.Errorf("clean.bash: %s", err)
- }
- // upload binary release
- fn := fmt.Sprintf("go.%s.%s-%s.tar.gz", release, b.goos, b.goarch)
- err = run(nil, workpath, "tar", "czf", fn, "go")
- if err != nil {
- return fmt.Errorf("tar: %s", err)
- }
- err = run(nil, workpath, path.Join(goroot, codePyScript),
- "-s", release,
- "-p", codeProject,
- "-u", b.codeUsername,
- "-w", b.codePassword,
- "-l", fmt.Sprintf("%s,%s", b.goos, b.goarch),
- fn)
- }
-
- return
-}
-
-// envv returns an environment for build/bench execution
-func (b *Builder) envv() []string {
- if runtime.GOOS == "windows" {
- return b.envvWindows()
- }
- e := []string{
- "GOOS=" + b.goos,
- "GOARCH=" + b.goarch,
- "GOROOT_FINAL=/usr/local/go",
- }
- for _, k := range extraEnv {
- s, err := os.Getenverror(k)
- if err == nil {
- e = append(e, k+"="+s)
- }
- }
- return e
-}
-
-// windows version of envv
-func (b *Builder) envvWindows() []string {
- start := map[string]string{
- "GOOS": b.goos,
- "GOARCH": b.goarch,
- "GOROOT_FINAL": "/c/go",
- // TODO(brainman): remove once we find make that does not hang.
- "MAKEFLAGS": "-j1",
- }
- for _, name := range extraEnv {
- s, err := os.Getenverror(name)
- if err == nil {
- start[name] = s
- }
- }
- skip := map[string]bool{
- "GOBIN": true,
- "GOROOT": true,
- "INCLUDE": true,
- "LIB": true,
- }
- var e []string
- for name, v := range start {
- e = append(e, name+"="+v)
- skip[name] = true
- }
- for _, kv := range os.Environ() {
- s := strings.SplitN(kv, "=", 2)
- name := strings.ToUpper(s[0])
- switch {
- case name == "":
- // variables, like "=C:=C:\", just copy them
- e = append(e, kv)
- case !skip[name]:
- e = append(e, kv)
- skip[name] = true
- }
- }
- return e
-}
-
-func isDirectory(name string) bool {
- s, err := os.Stat(name)
- return err == nil && s.IsDirectory()
-}
-
-func isFile(name string) bool {
- s, err := os.Stat(name)
- return err == nil && (s.IsRegular() || s.IsSymlink())
-}
-
-// commitWatcher polls hg for new commits and tells the dashboard about them.
-func commitWatcher() {
- // Create builder just to get master key.
- b, err := NewBuilder("mercurial-commit")
- if err != nil {
- log.Fatal(err)
- }
- for {
- if *verbose {
- log.Printf("poll...")
- }
- commitPoll(b.key)
- if *verbose {
- log.Printf("sleep...")
- }
- time.Sleep(60e9)
- }
-}
-
-// HgLog represents a single Mercurial revision.
-type HgLog struct {
- Hash string
- Author string
- Date string
- Desc string
- Parent string
-
- // Internal metadata
- added bool
-}
-
-// logByHash is a cache of all Mercurial revisions we know about,
-// indexed by full hash.
-var logByHash = map[string]*HgLog{}
-
-// xmlLogTemplate is a template to pass to Mercurial to make
-// hg log print the log in valid XML for parsing with xml.Unmarshal.
-const xmlLogTemplate = `
- <log>
- <hash>{node|escape}</hash>
- <parent>{parent|escape}</parent>
- <author>{author|escape}</author>
- <date>{date}</date>
- <desc>{desc|escape}</desc>
- </log>
-`
-
-// commitPoll pulls any new revisions from the hg server
-// and tells the server about them.
-func commitPoll(key string) {
- // Catch unexpected panics.
- defer func() {
- if err := recover(); err != nil {
- log.Printf("commitPoll panic: %s", err)
- }
- }()
-
- if err := run(nil, goroot, "hg", "pull"); err != nil {
- log.Printf("hg pull: %v", err)
- return
- }
-
- const N = 20 // how many revisions to grab
-
- data, _, err := runLog(nil, "", goroot, "hg", "log",
- "--encoding=utf-8",
- "--limit="+strconv.Itoa(N),
- "--template="+xmlLogTemplate,
- )
- if err != nil {
- log.Printf("hg log: %v", err)
- return
- }
-
- var logStruct struct {
- Log []HgLog
- }
- err = xml.Unmarshal(strings.NewReader("<top>"+data+"</top>"), &logStruct)
- if err != nil {
- log.Printf("unmarshal hg log: %v", err)
- return
- }
-
- logs := logStruct.Log
-
- // Pass 1. Fill in parents and add new log entries to logsByHash.
- // Empty parent means take parent from next log entry.
- // Non-empty parent has form 1234:hashhashhash; we want full hash.
- for i := range logs {
- l := &logs[i]
- log.Printf("hg log: %s < %s\n", l.Hash, l.Parent)
- if l.Parent == "" && i+1 < len(logs) {
- l.Parent = logs[i+1].Hash
- } else if l.Parent != "" {
- l.Parent, _ = fullHash(l.Parent)
- }
- if l.Parent == "" {
- // Can't create node without parent.
- continue
- }
-
- if logByHash[l.Hash] == nil {
- // Make copy to avoid pinning entire slice when only one entry is new.
- t := *l
- logByHash[t.Hash] = &t
- }
- }
-
- for i := range logs {
- l := &logs[i]
- if l.Parent == "" {
- continue
- }
- addCommit(l.Hash, key)
- }
-}
-
-// addCommit adds the commit with the named hash to the dashboard.
-// key is the secret key for authentication to the dashboard.
-// It avoids duplicate effort.
-func addCommit(hash, key string) bool {
- l := logByHash[hash]
- if l == nil {
- return false
- }
- if l.added {
- return true
- }
-
- // Check for already added, perhaps in an earlier run.
- if dashboardCommit(hash) {
- log.Printf("%s already on dashboard\n", hash)
- // Record that this hash is on the dashboard,
- // as must be all its parents.
- for l != nil {
- l.added = true
- l = logByHash[l.Parent]
- }
- return true
- }
-
- // Create parent first, to maintain some semblance of order.
- if !addCommit(l.Parent, key) {
- return false
- }
-
- // Create commit.
- if err := postCommit(key, l); err != nil {
- log.Printf("failed to add %s to dashboard: %v", key, err)
- return false
- }
- return true
-}
-
-// fullHash returns the full hash for the given Mercurial revision.
-func fullHash(rev string) (hash string, err os.Error) {
- defer func() {
- if err != nil {
- err = fmt.Errorf("fullHash: %s: %s", rev, err)
- }
- }()
- s, _, err := runLog(nil, "", goroot,
- "hg", "log",
- "--encoding=utf-8",
- "--rev="+rev,
- "--limit=1",
- "--template={node}",
- )
- if err != nil {
- return
- }
- s = strings.TrimSpace(s)
- if s == "" {
- return "", fmt.Errorf("cannot find revision")
- }
- if len(s) != 40 {
- return "", fmt.Errorf("hg returned invalid hash " + s)
- }
- return s, nil
-}
-
-var revisionRe = regexp.MustCompile(`^([^ ]+) +[0-9]+:([0-9a-f]+)$`)
-
-// firstTag returns the hash and tag of the most recent tag matching re.
-func firstTag(re *regexp.Regexp) (hash string, tag string, err os.Error) {
- o, _, err := runLog(nil, "", goroot, "hg", "tags")
- for _, l := range strings.Split(o, "\n") {
- if l == "" {
- continue
- }
- s := revisionRe.FindStringSubmatch(l)
- if s == nil {
- err = os.NewError("couldn't find revision number")
- return
- }
- if !re.MatchString(s[1]) {
- continue
- }
- tag = s[1]
- hash, err = fullHash(s[2])
- return
- }
- err = os.NewError("no matching tag found")
- return
-}
diff --git a/misc/dashboard/builder/package.go b/misc/dashboard/builder/package.go
deleted file mode 100644
index b6674428d..000000000
--- a/misc/dashboard/builder/package.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// 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 (
- "go/doc"
- "go/parser"
- "go/token"
- "log"
- "os"
- "path/filepath"
- "strings"
-)
-
-const MaxCommentLength = 500 // App Engine won't store more in a StringProperty.
-
-func (b *Builder) buildPackages(workpath string, hash string) os.Error {
- pkgs, err := packages()
- if err != nil {
- return err
- }
- for _, p := range pkgs {
- goroot := filepath.Join(workpath, "go")
- gobin := filepath.Join(goroot, "bin")
- goinstall := filepath.Join(gobin, "goinstall")
- envv := append(b.envv(), "GOROOT="+goroot)
-
- // add GOBIN to path
- for i, v := range envv {
- if strings.HasPrefix(v, "PATH=") {
- p := filepath.SplitList(v[5:])
- p = append([]string{gobin}, p...)
- s := strings.Join(p, string(filepath.ListSeparator))
- envv[i] = "PATH=" + s
- }
- }
-
- // goinstall
- buildLog, code, err := runLog(envv, "", goroot, goinstall, "-log=false", p)
- if err != nil {
- log.Printf("goinstall %v: %v", p, err)
- }
-
- // get doc comment from package source
- info, err := packageComment(p, filepath.Join(goroot, "src", "pkg", p))
- if err != nil {
- log.Printf("packageComment %v: %v", p, err)
- }
-
- // update dashboard with build state + info
- err = b.updatePackage(p, code == 0, buildLog, info)
- if err != nil {
- log.Printf("updatePackage %v: %v", p, err)
- }
- }
- return nil
-}
-
-func isGoFile(fi *os.FileInfo) bool {
- return fi.IsRegular() && // exclude directories
- !strings.HasPrefix(fi.Name, ".") && // ignore .files
- filepath.Ext(fi.Name) == ".go"
-}
-
-func packageComment(pkg, pkgpath string) (info string, err os.Error) {
- fset := token.NewFileSet()
- pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
- if err != nil {
- return
- }
- for name := range pkgs {
- if name == "main" {
- continue
- }
- if info != "" {
- return "", os.NewError("multiple non-main package docs")
- }
- pdoc := doc.NewPackageDoc(pkgs[name], pkg)
- info = pdoc.Doc
- }
- // grab only first paragraph
- if parts := strings.SplitN(info, "\n\n", 2); len(parts) > 1 {
- info = parts[0]
- }
- // replace newlines with spaces
- info = strings.Replace(info, "\n", " ", -1)
- // truncate
- if len(info) > MaxCommentLength {
- info = info[:MaxCommentLength]
- }
- return
-}