application: golang-org
version: build
runtime: go
-api_version: 3
+api_version: go1beta
handlers:
- url: /static
"bytes"
"compress/gzip"
"crypto/sha1"
+ "errors"
"fmt"
"io"
"io/ioutil"
- "os"
"strings"
+ "time"
"appengine"
"appengine/datastore"
}
// LastCommit returns the most recent Commit for this Package.
-func (p *Package) LastCommit(c appengine.Context) (*Commit, os.Error) {
+func (p *Package) LastCommit(c appengine.Context) (*Commit, error) {
var commits []*Commit
_, err := datastore.NewQuery("Commit").
Ancestor(p.Key(c)).
}
// GetPackage fetches a Package by path from the datastore.
-func GetPackage(c appengine.Context, path string) (*Package, os.Error) {
+func GetPackage(c appengine.Context, path string) (*Package, error) {
p := &Package{Path: path}
err := datastore.Get(c, p.Key(c), p)
if err == datastore.ErrNoSuchEntity {
User string
Desc string `datastore:",noindex"`
- Time datastore.Time
+ Time time.Time
// ResultData is the Data string of each build Result for this Commit.
// For non-Go commits, only the Results for the current Go tip, weekly,
return datastore.NewKey(c, "Commit", key, 0, p.Key(c))
}
-func (c *Commit) Valid() os.Error {
+func (c *Commit) Valid() error {
if !validHash(c.Hash) {
- return os.NewError("invalid Hash")
+ return errors.New("invalid Hash")
}
if c.ParentHash != "" && !validHash(c.ParentHash) { // empty is OK
- return os.NewError("invalid ParentHash")
+ return errors.New("invalid ParentHash")
}
return nil
}
// AddResult adds the denormalized Reuslt data to the Commit's Result field.
// It must be called from inside a datastore transaction.
-func (com *Commit) AddResult(c appengine.Context, r *Result) os.Error {
+func (com *Commit) AddResult(c appengine.Context, r *Result) error {
if err := datastore.Get(c, com.Key(c), com); err != nil {
return fmt.Errorf("getting Commit: %v", err)
}
return datastore.NewKey(c, "Result", key, 0, p.Key(c))
}
-func (r *Result) Valid() os.Error {
+func (r *Result) Valid() error {
if !validHash(r.Hash) {
- return os.NewError("invalid Hash")
+ return errors.New("invalid Hash")
}
if r.PackagePath != "" && !validHash(r.GoHash) {
- return os.NewError("invalid GoHash")
+ return errors.New("invalid GoHash")
}
return nil
}
CompressedLog []byte
}
-func (l *Log) Text() ([]byte, os.Error) {
+func (l *Log) Text() ([]byte, error) {
d, err := gzip.NewReader(bytes.NewBuffer(l.CompressedLog))
if err != nil {
return nil, fmt.Errorf("reading log data: %v", err)
return b, nil
}
-func PutLog(c appengine.Context, text string) (hash string, err os.Error) {
+func PutLog(c appengine.Context, text string) (hash string, err error) {
h := sha1.New()
io.WriteString(h, text)
b := new(bytes.Buffer)
z, _ := gzip.NewWriterLevel(b, gzip.BestCompression)
io.WriteString(z, text)
z.Close()
- hash = fmt.Sprintf("%x", h.Sum())
+ hash = fmt.Sprintf("%x", h.Sum(nil))
key := datastore.NewKey(c, "Log", hash, 0, nil)
_, err = datastore.Put(c, key, &Log{b.Bytes()})
return
return datastore.NewKey(c, "Tag", t.Kind, 0, p.Key(c))
}
-func (t *Tag) Valid() os.Error {
+func (t *Tag) Valid() error {
if t.Kind != "weekly" && t.Kind != "release" && t.Kind != "tip" {
- return os.NewError("invalid Kind")
+ return errors.New("invalid Kind")
}
if !validHash(t.Hash) {
- return os.NewError("invalid Hash")
+ return errors.New("invalid Hash")
}
return nil
}
// Commit returns the Commit that corresponds with this Tag.
-func (t *Tag) Commit(c appengine.Context) (*Commit, os.Error) {
+func (t *Tag) Commit(c appengine.Context) (*Commit, error) {
com := &Commit{Hash: t.Hash}
err := datastore.Get(c, com.Key(c), com)
return com, err
}
// GetTag fetches a Tag by name from the datastore.
-func GetTag(c appengine.Context, tag string) (*Tag, os.Error) {
+func GetTag(c appengine.Context, tag string) (*Tag, error) {
t := &Tag{Kind: tag}
if err := datastore.Get(c, t.Key(c), t); err != nil {
if err == datastore.ErrNoSuchEntity {
- return nil, os.NewError("tag not found: " + tag)
+ return nil, errors.New("tag not found: " + tag)
}
return nil, err
}
// Packages returns packages of the specified kind.
// Kind must be one of "external" or "subrepo".
-func Packages(c appengine.Context, kind string) ([]*Package, os.Error) {
+func Packages(c appengine.Context, kind string) ([]*Package, error) {
switch kind {
case "external", "subrepo":
default:
- return nil, os.NewError(`kind must be one of "external" or "subrepo"`)
+ return nil, errors.New(`kind must be one of "external" or "subrepo"`)
}
var pkgs []*Package
q := datastore.NewQuery("Package").Filter("Kind=", kind)
import (
"crypto/hmac"
+ "crypto/md5"
+ "encoding/json"
+ "errors"
"fmt"
- "http"
- "json"
- "os"
+ "net/http"
"appengine"
"appengine/datastore"
// each new commit at tip.
//
// This handler is used by a gobuilder process in -commit mode.
-func commitHandler(r *http.Request) (interface{}, os.Error) {
+func commitHandler(r *http.Request) (interface{}, error) {
c := appengine.NewContext(r)
com := new(Commit)
return nil, fmt.Errorf("validating Commit: %v", err)
}
defer cache.Tick(c)
- tx := func(c appengine.Context) os.Error {
+ tx := func(c appengine.Context) error {
return addCommit(c, com)
}
return nil, datastore.RunInTransaction(c, tx, nil)
// addCommit adds the Commit entity to the datastore and updates the tip Tag.
// It must be run inside a datastore transaction.
-func addCommit(c appengine.Context, com *Commit) os.Error {
+func addCommit(c appengine.Context, com *Commit) error {
var tc Commit // temp value so we don't clobber com
err := datastore.Get(c, com.Key(c), &tc)
if err != datastore.ErrNoSuchEntity {
return fmt.Errorf("testing for parent Commit: %v", err)
}
if n == 0 {
- return os.NewError("parent commit not found")
+ return errors.New("parent commit not found")
}
}
// update the tip Tag if this is the Go repo
// request body and updates the Tag entity for the Kind of tag provided.
//
// This handler is used by a gobuilder process in -commit mode.
-func tagHandler(r *http.Request) (interface{}, os.Error) {
+func tagHandler(r *http.Request) (interface{}, error) {
if r.Method != "POST" {
return nil, errBadMethod(r.Method)
}
// todoHandler returns the next action to be performed by a builder.
// It expects "builder" and "kind" query parameters and returns a *Todo value.
// Multiple "kind" parameters may be specified.
-func todoHandler(r *http.Request) (interface{}, os.Error) {
+func todoHandler(r *http.Request) (interface{}, error) {
c := appengine.NewContext(r)
now := cache.Now(c)
key := "build-todo-" + r.Form.Encode()
if cache.Get(r, now, key, &todo) {
return todo, nil
}
- var err os.Error
+ var err error
builder := r.FormValue("builder")
for _, kind := range r.Form["kind"] {
var data interface{}
// If provided with non-empty packagePath and goHash args, it scans the first
// 20 Commits in Num-descending order for the specified packagePath and
// returns the first that doesn't have a Result for this builder and goHash.
-func buildTodo(c appengine.Context, builder, packagePath, goHash string) (interface{}, os.Error) {
+func buildTodo(c appengine.Context, builder, packagePath, goHash string) (interface{}, error) {
p, err := GetPackage(c, packagePath)
if err != nil {
return nil, err
// packagesHandler returns a list of the non-Go Packages monitored
// by the dashboard.
-func packagesHandler(r *http.Request) (interface{}, os.Error) {
+func packagesHandler(r *http.Request) (interface{}, error) {
kind := r.FormValue("kind")
c := appengine.NewContext(r)
now := cache.Now(c)
// creates a new Result entity, and updates the relevant Commit entity.
// If the Log field is not empty, resultHandler creates a new Log entity
// and updates the LogHash field before putting the Commit entity.
-func resultHandler(r *http.Request) (interface{}, os.Error) {
+func resultHandler(r *http.Request) (interface{}, error) {
if r.Method != "POST" {
return nil, errBadMethod(r.Method)
}
}
res.LogHash = hash
}
- tx := func(c appengine.Context) os.Error {
+ tx := func(c appengine.Context) error {
// check Package exists
if _, err := GetPackage(c, res.PackagePath); err != nil {
return fmt.Errorf("GetPackage: %v", err)
w.Write(b)
}
-type dashHandler func(*http.Request) (interface{}, os.Error)
+type dashHandler func(*http.Request) (interface{}, error)
type dashResponse struct {
Response interface{}
// the request has an unsuitable method.
type errBadMethod string
-func (e errBadMethod) String() string {
+func (e errBadMethod) Error() string {
return "bad method: " + string(e)
}
// request body when calling r.FormValue.
r.Form = r.URL.Query()
- var err os.Error
+ var err error
var resp interface{}
// Validate key query parameter for POST requests only.
key := r.FormValue("key")
builder := r.FormValue("builder")
if r.Method == "POST" && !validKey(c, key, builder) {
- err = os.NewError("invalid key: " + key)
+ err = errors.New("invalid key: " + key)
}
// Call the original HandlerFunc and return the response.
dashResp := &dashResponse{Response: resp}
if err != nil {
c.Errorf("%v", err)
- dashResp.Error = err.String()
+ dashResp.Error = err.Error()
}
w.Header().Set("Content-Type", "application/json")
if err = json.NewEncoder(w).Encode(dashResp); err != nil {
func keyHandler(w http.ResponseWriter, r *http.Request) {
builder := r.FormValue("builder")
if builder == "" {
- logErr(w, r, os.NewError("must supply builder in query string"))
+ logErr(w, r, errors.New("must supply builder in query string"))
return
}
c := appengine.NewContext(r)
}
func builderKey(c appengine.Context, builder string) string {
- h := hmac.NewMD5([]byte(secretKey(c)))
+ h := hmac.New(md5.New, []byte(secretKey(c)))
h.Write([]byte(builder))
- return fmt.Sprintf("%x", h.Sum())
+ return fmt.Sprintf("%x", h.Sum(nil))
}
-func logErr(w http.ResponseWriter, r *http.Request, err os.Error) {
+func logErr(w http.ResponseWriter, r *http.Request, err error) {
appengine.NewContext(r).Errorf("Error: %v", err)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, "Error: ", err)
import (
"fmt"
- "http"
+ "net/http"
"appengine"
"appengine/datastore"
datastore.Put(c, theKey.Key(c), &theKey.BuilderKey)
return theKey.Secret
}
- panic("cannot load builder key: " + err.String())
+ panic("cannot load builder key: " + err.Error())
}
return theKey.Secret
"appengine/delay"
"appengine/mail"
"bytes"
+ "encoding/gob"
"fmt"
- "gob"
- "os"
- "template"
+ "text/template"
)
const (
//
// This must be run in a datastore transaction, and the provided *Commit must
// have been retrieved from the datastore within that transaction.
-func notifyOnFailure(c appengine.Context, com *Commit, builder string) os.Error {
+func notifyOnFailure(c appengine.Context, com *Commit, builder string) error {
// TODO(adg): implement notifications for packages
if com.PackagePath != "" {
return nil
broken = com
}
}
- var err os.Error
+ var err error
if broken != nil && !broken.FailNotificationSent {
c.Infof("%s is broken commit; notifying", broken.Hash)
sendFailMailLater.Call(c, broken, builder) // add task to queue
}
// firstMatch executes the query q and loads the first entity into v.
-func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) os.Error {
+func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) error {
t := q.Limit(1).Run(c)
_, err := t.Next(v)
if err == datastore.Done {
var (
sendFailMailLater = delay.Func("sendFailMail", sendFailMail)
sendFailMailTmpl = template.Must(
- template.New("notify").Funcs(tmplFuncs).ParseFile("build/notify.txt"),
+ template.New("notify.txt").
+ Funcs(template.FuncMap(tmplFuncs)).
+ ParseFiles("build/notify.txt"),
)
)
"appengine"
"appengine/datastore"
"bytes"
+ "encoding/json"
+ "errors"
"fmt"
- "http"
- "http/httptest"
"io"
- "json"
- "os"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
"strings"
"time"
- "url"
)
func init() {
testPackage,
}
-var tCommitTime = time.Seconds() - 60*60*24*7
+var tCommitTime = time.Now().Add(-time.Hour * 24 * 7)
func tCommit(hash, parentHash string) *Commit {
- tCommitTime += 60 * 60 * 12 // each commit should have a different time
+ tCommitTime.Add(time.Hour) // each commit should have a different time
return &Commit{
Hash: hash,
ParentHash: parentHash,
- Time: datastore.Time(tCommitTime * 1e6),
+ Time: tCommitTime,
User: "adg",
Desc: "change description",
}
fmt.Fprint(w, "PASS")
}
-func nukeEntities(c appengine.Context, kinds []string) os.Error {
+func nukeEntities(c appengine.Context, kinds []string) error {
if !appengine.IsDevAppServer() {
- return os.NewError("can't nuke production data")
+ return errors.New("can't nuke production data")
}
var keys []*datastore.Key
for _, kind := range kinds {
import (
"bytes"
- "exp/template/html"
- "http"
- "os"
+ "errors"
+ "html/template"
+ "net/http"
"regexp"
"sort"
"strconv"
"strings"
- "template"
"appengine"
"appengine/datastore"
func init() {
http.HandleFunc("/", uiHandler)
- html.Escape(uiTemplate)
}
// uiHandler draws the build status page.
// goCommits gets a slice of the latest Commits to the Go repository.
// If page > 0 it paginates by commitsPerPage.
-func goCommits(c appengine.Context, page int) ([]*Commit, os.Error) {
+func goCommits(c appengine.Context, page int) ([]*Commit, error) {
q := datastore.NewQuery("Commit").
Ancestor((&Package{}).Key(c)).
Order("-Time").
}
// TagStateByName fetches the results for all Go subrepos at the specified Tag.
-func TagStateByName(c appengine.Context, name string) (*TagState, os.Error) {
+func TagStateByName(c appengine.Context, name string) (*TagState, error) {
tag, err := GetTag(c, name)
if err != nil {
return nil, err
}
var uiTemplate = template.Must(
- template.New("ui").Funcs(tmplFuncs).ParseFile("build/ui.html"),
+ template.New("ui.html").Funcs(tmplFuncs).ParseFiles("build/ui.html"),
)
var tmplFuncs = template.FuncMap{
var repoRe = regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+)(\.[a-z0-9\-]+)?$`)
// repoURL returns the URL of a change at a Google Code repository or subrepo.
-func repoURL(hash, packagePath string) (string, os.Error) {
+func repoURL(hash, packagePath string) (string, error) {
if packagePath == "" {
return "https://code.google.com/p/go/source/detail?r=" + hash, nil
}
m := repoRe.FindStringSubmatch(packagePath)
if m == nil {
- return "", os.NewError("unrecognized package: " + packagePath)
+ return "", errors.New("unrecognized package: " + packagePath)
}
url := "https://code.google.com/p/" + m[1] + "/source/detail?r=" + hash
if len(m) > 2 {
import (
"fmt"
- "http"
+ "net/http"
"time"
"appengine"
expiry = 600 // 10 minutes
)
-func newTime() uint64 { return uint64(time.Seconds()) << 32 }
+func newTime() uint64 { return uint64(time.Now().Unix()) << 32 }
// Now returns the current logical datastore time to use for cache lookups.
func Now(c appengine.Context) uint64 {