]> Cypherpunks repositories - gostls13.git/commitdiff
misc/dashboard/codereview: delete
authorAndrew Gerrand <adg@golang.org>
Mon, 19 Jan 2015 22:12:24 +0000 (09:12 +1100)
committerAndrew Gerrand <adg@golang.org>
Mon, 19 Jan 2015 22:18:03 +0000 (22:18 +0000)
This dashboard is no longer in use, and doesn't work with Gerrit.

Change-Id: Ib7c367dcad97322566610157b15e23db5bec58ff
Reviewed-on: https://go-review.googlesource.com/3028
Reviewed-by: David Symonds <dsymonds@golang.org>
misc/dashboard/codereview/app.yaml [deleted file]
misc/dashboard/codereview/cron.yaml [deleted file]
misc/dashboard/codereview/dashboard/cl.go [deleted file]
misc/dashboard/codereview/dashboard/front.go [deleted file]
misc/dashboard/codereview/dashboard/gc.go [deleted file]
misc/dashboard/codereview/dashboard/mail.go [deleted file]
misc/dashboard/codereview/dashboard/people.go [deleted file]
misc/dashboard/codereview/index.yaml [deleted file]
misc/dashboard/codereview/queue.yaml [deleted file]
misc/dashboard/codereview/static/gopherstamp.jpg [deleted file]
misc/dashboard/codereview/static/icon.png [deleted file]

diff --git a/misc/dashboard/codereview/app.yaml b/misc/dashboard/codereview/app.yaml
deleted file mode 100644 (file)
index 372eca5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-application: gocodereview
-version: 1
-runtime: go
-api_version: go1
-
-inbound_services:
-- mail
-
-handlers:
-- url: /static/(.*)
-  static_files: static/\1
-  upload: static/.*
-- url: /_ah/mail/.*
-  script: _go_app
-  login: admin
-- url: /_ah/queue/go/delay
-  script: _go_app
-  login: admin
-- url: /(gc|update-cl)
-  script: _go_app
-  login: admin
-- url: /.*
-  script: _go_app
-  login: required
diff --git a/misc/dashboard/codereview/cron.yaml b/misc/dashboard/codereview/cron.yaml
deleted file mode 100644 (file)
index 3d33d32..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-cron:
-- description: GC
-  url: /gc
-  schedule: every 6 hours
diff --git a/misc/dashboard/codereview/dashboard/cl.go b/misc/dashboard/codereview/dashboard/cl.go
deleted file mode 100644 (file)
index 0ef3303..0000000
+++ /dev/null
@@ -1,493 +0,0 @@
-// Copyright 2012 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 dashboard
-
-// This file handles operations on the CL entity kind.
-
-import (
-       "bytes"
-       "encoding/json"
-       "fmt"
-       "html/template"
-       "io"
-       "io/ioutil"
-       "net/http"
-       "net/url"
-       "regexp"
-       "sort"
-       "strings"
-       "time"
-
-       "appengine"
-       "appengine/datastore"
-       "appengine/taskqueue"
-       "appengine/urlfetch"
-       "appengine/user"
-)
-
-func init() {
-       http.HandleFunc("/assign", handleAssign)
-       http.HandleFunc("/update-cl", handleUpdateCL)
-}
-
-const codereviewBase = "http://codereview.appspot.com"
-const gobotBase = "http://research.swtch.com/gobot_codereview"
-
-var clRegexp = regexp.MustCompile(`\d+`)
-
-// CL represents a code review.
-type CL struct {
-       Number string // e.g. "5903061"
-       Closed bool
-       Owner  string // email address
-
-       Created, Modified time.Time
-
-       Description  []byte `datastore:",noindex"`
-       FirstLine    string `datastore:",noindex"`
-       LGTMs        []string
-       NotLGTMs     []string
-       LastUpdateBy string // author of most recent review message
-       LastUpdate   string `datastore:",noindex"` // first line of most recent review message
-
-       // Mail information.
-       Subject       string   `datastore:",noindex"`
-       Recipients    []string `datastore:",noindex"`
-       LastMessageID string   `datastore:",noindex"`
-
-       // These are person IDs (e.g. "rsc"); they may be empty
-       Author   string
-       Reviewer string
-}
-
-// Reviewed reports whether the reviewer has replied to the CL.
-// The heuristic is that the CL has been replied to if it is LGTMed
-// or if the last CL message was from the reviewer.
-func (cl *CL) Reviewed() bool {
-       if cl.LastUpdateBy == cl.Reviewer {
-               return true
-       }
-       if person := emailToPerson[cl.LastUpdateBy]; person != "" && person == cl.Reviewer {
-               return true
-       }
-       for _, who := range cl.LGTMs {
-               if who == cl.Reviewer {
-                       return true
-               }
-       }
-       return false
-}
-
-// DisplayOwner returns the CL's owner, either as their email address
-// or the person ID if it's a reviewer. It is for display only.
-func (cl *CL) DisplayOwner() string {
-       if p, ok := emailToPerson[cl.Owner]; ok {
-               return p
-       }
-       return cl.Owner
-}
-
-func (cl *CL) FirstLineHTML() template.HTML {
-       s := template.HTMLEscapeString(cl.FirstLine)
-       // Embolden the package name.
-       if i := strings.Index(s, ":"); i >= 0 {
-               s = "<b>" + s[:i] + "</b>" + s[i:]
-       }
-       return template.HTML(s)
-}
-
-func formatEmails(e []string) template.HTML {
-       x := make([]string, len(e))
-       for i, s := range e {
-               s = template.HTMLEscapeString(s)
-               if !strings.Contains(s, "@") {
-                       s = "<b>" + s + "</b>"
-               }
-               s = `<span class="email">` + s + "</span>"
-               x[i] = s
-       }
-       return template.HTML(strings.Join(x, ", "))
-}
-
-func (cl *CL) LGTMHTML() template.HTML {
-       return formatEmails(cl.LGTMs)
-}
-
-func (cl *CL) NotLGTMHTML() template.HTML {
-       return formatEmails(cl.NotLGTMs)
-}
-
-func (cl *CL) ModifiedAgo() string {
-       // Just the first non-zero unit.
-       units := [...]struct {
-               suffix string
-               unit   time.Duration
-       }{
-               {"d", 24 * time.Hour},
-               {"h", time.Hour},
-               {"m", time.Minute},
-               {"s", time.Second},
-       }
-       d := time.Now().Sub(cl.Modified)
-       for _, u := range units {
-               if d > u.unit {
-                       return fmt.Sprintf("%d%s", d/u.unit, u.suffix)
-               }
-       }
-       return "just now"
-}
-
-func handleAssign(w http.ResponseWriter, r *http.Request) {
-       c := appengine.NewContext(r)
-
-       if r.Method != "POST" {
-               http.Error(w, "Bad method "+r.Method, 400)
-               return
-       }
-
-       u := user.Current(c)
-       person, ok := emailToPerson[u.Email]
-       if !ok {
-               http.Error(w, "Not allowed", http.StatusUnauthorized)
-               return
-       }
-
-       n, rev := r.FormValue("cl"), r.FormValue("r")
-       if !clRegexp.MatchString(n) {
-               c.Errorf("Bad CL %q", n)
-               http.Error(w, "Bad CL", 400)
-               return
-       }
-       if _, ok := preferredEmail[rev]; !ok && rev != "" {
-               c.Errorf("Unknown reviewer %q", rev)
-               http.Error(w, "Unknown reviewer", 400)
-               return
-       }
-
-       key := datastore.NewKey(c, "CL", n, 0, nil)
-
-       if rev != "" {
-               // Make sure the reviewer is listed in Rietveld as a reviewer.
-               url := codereviewBase + "/" + n + "/fields"
-               resp, err := urlfetch.Client(c).Get(url + "?field=reviewers")
-               if err != nil {
-                       c.Errorf("Retrieving CL reviewer list failed: %v", err)
-                       http.Error(w, err.Error(), 500)
-                       return
-               }
-               defer resp.Body.Close()
-               body, err := ioutil.ReadAll(resp.Body)
-               if err != nil {
-                       c.Errorf("Failed reading body: %v", err)
-                       http.Error(w, err.Error(), 500)
-                       return
-               }
-               if resp.StatusCode != 200 {
-                       c.Errorf("Retrieving CL reviewer list failed: got HTTP response %d\nBody: %s", resp.StatusCode, body)
-                       http.Error(w, "Failed contacting Rietveld", 500)
-                       return
-               }
-
-               var apiResp struct {
-                       Reviewers []string `json:"reviewers"`
-               }
-               if err := json.Unmarshal(body, &apiResp); err != nil {
-                       // probably can't be retried
-                       msg := fmt.Sprintf("Malformed JSON from %v: %v", url, err)
-                       c.Errorf("%s", msg)
-                       http.Error(w, msg, 500)
-                       return
-               }
-               found := false
-               for _, r := range apiResp.Reviewers {
-                       if emailToPerson[r] == rev {
-                               found = true
-                               break
-                       }
-               }
-               if !found {
-                       c.Infof("Adding %v as a reviewer of CL %v", rev, n)
-
-                       url := fmt.Sprintf("%s?cl=%s&r=%s&obo=%s", gobotBase, n, rev, person)
-                       resp, err := urlfetch.Client(c).Get(url)
-                       if err != nil {
-                               c.Errorf("Gobot GET failed: %v", err)
-                               http.Error(w, err.Error(), 500)
-                               return
-                       }
-                       defer resp.Body.Close()
-                       body, err := ioutil.ReadAll(resp.Body)
-                       if err != nil {
-                               c.Errorf("Failed reading Gobot body: %v", err)
-                               http.Error(w, err.Error(), 500)
-                               return
-                       }
-                       if resp.StatusCode != 200 {
-                               c.Errorf("Gobot GET failed: got HTTP response %d\nBody: %s", resp.StatusCode, body)
-                               http.Error(w, "Failed contacting Gobot", 500)
-                               return
-                       }
-
-                       c.Infof("Gobot said %q", resp.Status)
-               }
-       }
-
-       // Update our own record.
-       err := datastore.RunInTransaction(c, func(c appengine.Context) error {
-               cl := new(CL)
-               err := datastore.Get(c, key, cl)
-               if err != nil {
-                       return err
-               }
-               cl.Reviewer = rev
-               _, err = datastore.Put(c, key, cl)
-               return err
-       }, nil)
-       if err != nil {
-               msg := fmt.Sprintf("Assignment failed: %v", err)
-               c.Errorf("%s", msg)
-               http.Error(w, msg, 500)
-               return
-       }
-       c.Infof("Assigned CL %v to %v", n, rev)
-}
-
-func UpdateCLLater(c appengine.Context, n string, delay time.Duration) {
-       t := taskqueue.NewPOSTTask("/update-cl", url.Values{
-               "cl": []string{n},
-       })
-       t.Delay = delay
-       if _, err := taskqueue.Add(c, t, "update-cl"); err != nil {
-               c.Errorf("Failed adding task: %v", err)
-       }
-}
-
-func handleUpdateCL(w http.ResponseWriter, r *http.Request) {
-       c := appengine.NewContext(r)
-
-       n := r.FormValue("cl")
-       if !clRegexp.MatchString(n) {
-               c.Errorf("Bad CL %q", n)
-               http.Error(w, "Bad CL", 400)
-               return
-       }
-
-       if err := updateCL(c, n); err != nil {
-               c.Errorf("Failed updating CL %v: %v", n, err)
-               http.Error(w, "Failed update", 500)
-               return
-       }
-
-       io.WriteString(w, "OK")
-}
-
-// apiMessage describes the JSON sent back by Rietveld in the CL messages list.
-type apiMessage struct {
-       Date       string   `json:"date"`
-       Text       string   `json:"text"`
-       Sender     string   `json:"sender"`
-       Recipients []string `json:"recipients"`
-       Approval   bool     `json:"approval"`
-}
-
-// byDate implements sort.Interface to order the messages by date, earliest first.
-// The dates are sent in RFC 3339 format, so string comparison matches time value comparison.
-type byDate []*apiMessage
-
-func (x byDate) Len() int           { return len(x) }
-func (x byDate) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
-func (x byDate) Less(i, j int) bool { return x[i].Date < x[j].Date }
-
-// updateCL updates a single CL. If a retryable failure occurs, an error is returned.
-func updateCL(c appengine.Context, n string) error {
-       c.Debugf("Updating CL %v", n)
-       key := datastore.NewKey(c, "CL", n, 0, nil)
-
-       url := codereviewBase + "/api/" + n + "?messages=true"
-       resp, err := urlfetch.Client(c).Get(url)
-       if err != nil {
-               return err
-       }
-       defer resp.Body.Close()
-
-       raw, err := ioutil.ReadAll(resp.Body)
-       if err != nil {
-               return fmt.Errorf("Failed reading HTTP body: %v", err)
-       }
-
-       // Special case for abandoned CLs.
-       if resp.StatusCode == 404 && bytes.Contains(raw, []byte("No issue exists with that id")) {
-               // Don't bother checking for errors. The CL might never have been saved, for instance.
-               datastore.Delete(c, key)
-               c.Infof("Deleted abandoned CL %v", n)
-               return nil
-       }
-
-       if resp.StatusCode != 200 {
-               return fmt.Errorf("Update: got HTTP response %d", resp.StatusCode)
-       }
-
-       var apiResp struct {
-               Description string        `json:"description"`
-               Reviewers   []string      `json:"reviewers"`
-               Created     string        `json:"created"`
-               OwnerEmail  string        `json:"owner_email"`
-               Modified    string        `json:"modified"`
-               Closed      bool          `json:"closed"`
-               Subject     string        `json:"subject"`
-               Messages    []*apiMessage `json:"messages"`
-       }
-       if err := json.Unmarshal(raw, &apiResp); err != nil {
-               // probably can't be retried
-               c.Errorf("Malformed JSON from %v: %v", url, err)
-               return nil
-       }
-       //c.Infof("RAW: %+v", apiResp)
-       sort.Sort(byDate(apiResp.Messages))
-
-       cl := &CL{
-               Number:      n,
-               Closed:      apiResp.Closed,
-               Owner:       apiResp.OwnerEmail,
-               Description: []byte(apiResp.Description),
-               FirstLine:   apiResp.Description,
-               Subject:     apiResp.Subject,
-               Author:      emailToPerson[apiResp.OwnerEmail],
-       }
-       cl.Created, err = time.Parse("2006-01-02 15:04:05.000000", apiResp.Created)
-       if err != nil {
-               c.Errorf("Bad creation time %q: %v", apiResp.Created, err)
-       }
-       cl.Modified, err = time.Parse("2006-01-02 15:04:05.000000", apiResp.Modified)
-       if err != nil {
-               c.Errorf("Bad modification time %q: %v", apiResp.Modified, err)
-       }
-       if i := strings.Index(cl.FirstLine, "\n"); i >= 0 {
-               cl.FirstLine = cl.FirstLine[:i]
-       }
-       // Treat zero reviewers as a signal that the CL is completed.
-       // This could be after the CL has been submitted, but before the CL author has synced,
-       // but it could also be a CL manually edited to remove reviewers.
-       if len(apiResp.Reviewers) == 0 {
-               cl.Closed = true
-       }
-
-       lgtm := make(map[string]bool)
-       notLGTM := make(map[string]bool)
-       rcpt := make(map[string]bool)
-       for _, msg := range apiResp.Messages {
-               s, rev := msg.Sender, false
-               if p, ok := emailToPerson[s]; ok {
-                       s, rev = p, true
-               }
-
-               line := firstLine(msg.Text)
-               if line != "" {
-                       cl.LastUpdateBy = msg.Sender
-                       cl.LastUpdate = line
-               }
-
-               // CLs submitted by someone other than the CL owner do not immediately
-               // transition to "closed". Let's simulate the intention by treating
-               // messages starting with "*** Submitted as " from a reviewer as a
-               // signal that the CL is now closed.
-               if rev && strings.HasPrefix(msg.Text, "*** Submitted as ") {
-                       cl.Closed = true
-               }
-
-               if msg.Approval {
-                       lgtm[s] = true
-                       delete(notLGTM, s) // "LGTM" overrules previous "NOT LGTM"
-               }
-               if strings.Contains(line, "NOT LGTM") {
-                       notLGTM[s] = true
-                       delete(lgtm, s) // "NOT LGTM" overrules previous "LGTM"
-               }
-
-               for _, r := range msg.Recipients {
-                       rcpt[r] = true
-               }
-       }
-       for l := range lgtm {
-               cl.LGTMs = append(cl.LGTMs, l)
-       }
-       for l := range notLGTM {
-               cl.NotLGTMs = append(cl.NotLGTMs, l)
-       }
-       for r := range rcpt {
-               cl.Recipients = append(cl.Recipients, r)
-       }
-       sort.Strings(cl.LGTMs)
-       sort.Strings(cl.NotLGTMs)
-       sort.Strings(cl.Recipients)
-
-       err = datastore.RunInTransaction(c, func(c appengine.Context) error {
-               ocl := new(CL)
-               err := datastore.Get(c, key, ocl)
-               if err != nil && err != datastore.ErrNoSuchEntity {
-                       return err
-               } else if err == nil {
-                       // LastMessageID and Reviewer need preserving.
-                       cl.LastMessageID = ocl.LastMessageID
-                       cl.Reviewer = ocl.Reviewer
-               }
-               _, err = datastore.Put(c, key, cl)
-               return err
-       }, nil)
-       if err != nil {
-               return err
-       }
-       c.Infof("Updated CL %v", n)
-       return nil
-}
-
-// trailingSpaceRE matches trailing spaces.
-var trailingSpaceRE = regexp.MustCompile(`(?m)[ \t\r]+$`)
-
-// removeRE is the list of patterns to skip over at the beginning of a
-// message when looking for message text.
-var removeRE = regexp.MustCompile(`(?m-s)\A(` +
-       // Skip leading "Hello so-and-so," generated by codereview plugin.
-       `(Hello(.|\n)*?\n\n)` +
-
-       // Skip quoted text.
-       `|((On.*|.* writes|.* wrote):\n)` +
-       `|((>.*\n)+)` +
-
-       // Skip lines with no letters.
-       `|(([^A-Za-z]*\n)+)` +
-
-       // Skip links to comments and file info.
-       `|(http://codereview.*\n([^ ]+:[0-9]+:.*\n)?)` +
-       `|(File .*:\n)` +
-
-       `)`,
-)
-
-// firstLine returns the first interesting line of the message text.
-func firstLine(text string) string {
-       // Cut trailing spaces.
-       text = trailingSpaceRE.ReplaceAllString(text, "")
-
-       // Skip uninteresting lines.
-       for {
-               text = strings.TrimSpace(text)
-               m := removeRE.FindStringIndex(text)
-               if m == nil || m[0] != 0 {
-                       break
-               }
-               text = text[m[1]:]
-       }
-
-       // Chop line at newline or else at 74 bytes.
-       i := strings.Index(text, "\n")
-       if i >= 0 {
-               text = text[:i]
-       }
-       if len(text) > 74 {
-               text = text[:70] + "..."
-       }
-       return text
-}
diff --git a/misc/dashboard/codereview/dashboard/front.go b/misc/dashboard/codereview/dashboard/front.go
deleted file mode 100644 (file)
index ea9fe0d..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2012 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 dashboard
-
-// This file handles the front page.
-
-import (
-       "bytes"
-       "html/template"
-       "io"
-       "net/http"
-       "strings"
-       "sync"
-       "time"
-
-       "appengine"
-       "appengine/datastore"
-       "appengine/user"
-)
-
-func init() {
-       http.HandleFunc("/", handleFront)
-       http.HandleFunc("/favicon.ico", http.NotFound)
-}
-
-// maximum number of active CLs to show in person-specific tables.
-const maxCLs = 100
-
-func handleFront(w http.ResponseWriter, r *http.Request) {
-       c := appengine.NewContext(r)
-
-       data := &frontPageData{
-               Reviewers: personList,
-               User:      user.Current(c).Email,
-               IsAdmin:   user.IsAdmin(c),
-       }
-       var currentPerson string
-       u := data.User
-       you := "you"
-       if e := r.FormValue("user"); e != "" {
-               u = e
-               you = e
-       }
-       currentPerson, data.UserIsReviewer = emailToPerson[u]
-       if !data.UserIsReviewer {
-               currentPerson = u
-       }
-
-       var wg sync.WaitGroup
-       errc := make(chan error, 10)
-       activeCLs := datastore.NewQuery("CL").
-               Filter("Closed =", false).
-               Order("-Modified")
-
-       tableFetch := func(index int, f func(tbl *clTable) error) {
-               wg.Add(1)
-               go func() {
-                       defer wg.Done()
-                       start := time.Now()
-                       if err := f(&data.Tables[index]); err != nil {
-                               errc <- err
-                       }
-                       data.Timing[index] = time.Now().Sub(start)
-               }()
-       }
-
-       data.Tables[0].Title = "CLs assigned to " + you + " for review"
-       if data.UserIsReviewer {
-               tableFetch(0, func(tbl *clTable) error {
-                       q := activeCLs.Filter("Reviewer =", currentPerson).Limit(maxCLs)
-                       tbl.Assignable = true
-                       _, err := q.GetAll(c, &tbl.CLs)
-                       return err
-               })
-       }
-
-       tableFetch(1, func(tbl *clTable) error {
-               q := activeCLs
-               if data.UserIsReviewer {
-                       q = q.Filter("Author =", currentPerson)
-               } else {
-                       q = q.Filter("Owner =", currentPerson)
-               }
-               q = q.Limit(maxCLs)
-               tbl.Title = "CLs sent by " + you
-               tbl.Assignable = true
-               _, err := q.GetAll(c, &tbl.CLs)
-               return err
-       })
-
-       tableFetch(2, func(tbl *clTable) error {
-               q := activeCLs.Limit(50)
-               tbl.Title = "Other active CLs"
-               tbl.Assignable = true
-               if _, err := q.GetAll(c, &tbl.CLs); err != nil {
-                       return err
-               }
-               // filter
-               for i := len(tbl.CLs) - 1; i >= 0; i-- {
-                       cl := tbl.CLs[i]
-                       if cl.Owner == currentPerson || cl.Author == currentPerson || cl.Reviewer == currentPerson {
-                               // Preserve order.
-                               copy(tbl.CLs[i:], tbl.CLs[i+1:])
-                               tbl.CLs = tbl.CLs[:len(tbl.CLs)-1]
-                       }
-               }
-               return nil
-       })
-
-       tableFetch(3, func(tbl *clTable) error {
-               q := datastore.NewQuery("CL").
-                       Filter("Closed =", true).
-                       Order("-Modified").
-                       Limit(10)
-               tbl.Title = "Recently closed CLs"
-               tbl.Assignable = false
-               _, err := q.GetAll(c, &tbl.CLs)
-               return err
-       })
-
-       // Not really a table fetch.
-       tableFetch(0, func(_ *clTable) error {
-               var err error
-               data.LogoutURL, err = user.LogoutURL(c, "/")
-               return err
-       })
-
-       wg.Wait()
-
-       select {
-       case err := <-errc:
-               c.Errorf("%v", err)
-               http.Error(w, err.Error(), http.StatusInternalServerError)
-               return
-       default:
-       }
-
-       var b bytes.Buffer
-       if err := frontPage.ExecuteTemplate(&b, "front", &data); err != nil {
-               http.Error(w, err.Error(), http.StatusInternalServerError)
-               return
-       }
-
-       io.Copy(w, &b)
-}
-
-type frontPageData struct {
-       Tables [4]clTable
-       Timing [4]time.Duration
-
-       Reviewers      []string
-       UserIsReviewer bool
-
-       User, LogoutURL string // actual logged in user
-       IsAdmin         bool
-}
-
-type clTable struct {
-       Title      string
-       Assignable bool
-       CLs        []*CL
-}
-
-var frontPage = template.Must(template.New("front").Funcs(template.FuncMap{
-       "selected": func(a, b string) string {
-               if a == b {
-                       return "selected"
-               }
-               return ""
-       },
-       "shortemail": func(s string) string {
-               if i := strings.Index(s, "@"); i >= 0 {
-                       s = s[:i]
-               }
-               return s
-       },
-}).Parse(`
-<!doctype html>
-<html>
-  <head>
-    <title>Go code reviews</title>
-    <link rel="icon" type="image/png" href="/static/icon.png" />
-    <style type="text/css">
-      body {
-        font-family: Helvetica, sans-serif;
-      }
-      img#gopherstamp {
-        float: right;
-       height: auto;
-       width: 250px;
-      }
-      h1, h2, h3 {
-        color: #777;
-       margin-bottom: 0;
-      }
-      table {
-        border-spacing: 0;
-      }
-      td {
-        vertical-align: top;
-        padding: 2px 5px;
-      }
-      tr.unreplied td.email {
-        border-left: 2px solid blue;
-      }
-      tr.pending td {
-        background: #fc8;
-      }
-      tr.failed td {
-        background: #f88;
-      }
-      tr.saved td {
-        background: #8f8;
-      }
-      .cls {
-        margin-top: 0;
-      }
-      a {
-        color: blue;
-       text-decoration: none;  /* no link underline */
-      }
-      address {
-        font-size: 10px;
-       text-align: right;
-      }
-      .email {
-        font-family: monospace;
-      }
-    </style>
-    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
-  </head>
-  <body>
-
-<img id="gopherstamp" src="/static/gopherstamp.jpg" />
-<h1>Go code reviews</h1>
-
-<table class="cls">
-{{range $i, $tbl := .Tables}}
-<tr><td colspan="5"><h3>{{$tbl.Title}}</h3></td></tr>
-{{if .CLs}}
-{{range $cl := .CLs}}
-  <tr id="cl-{{$cl.Number}}" class="{{if not $i}}{{if not .Reviewed}}unreplied{{end}}{{end}}">
-    <td class="email">{{$cl.DisplayOwner}}</td>
-    <td>
-    {{if $tbl.Assignable}}
-    <select id="cl-rev-{{$cl.Number}}" {{if not $.UserIsReviewer}}disabled{{end}}>
-      <option></option>
-      {{range $.Reviewers}}
-      <option {{selected . $cl.Reviewer}}>{{.}}</option>
-      {{end}}
-    </select>
-    <script type="text/javascript">
-    $(function() {
-      $('#cl-rev-{{$cl.Number}}').change(function() {
-        var r = $(this).val();
-        var row = $('tr#cl-{{$cl.Number}}');
-        row.addClass('pending');
-        $.post('/assign', {
-          'cl': '{{$cl.Number}}',
-          'r': r
-        }).success(function() {
-          row.removeClass('pending');
-          row.addClass('saved');
-        }).error(function() {
-          row.removeClass('pending');
-          row.addClass('failed');
-        });
-      });
-    });
-    </script>
-    {{end}}
-    </td>
-    <td>
-      <a href="http://codereview.appspot.com/{{.Number}}/" title="{{ printf "%s" .Description}}">{{.Number}}: {{.FirstLineHTML}}</a>
-      {{if and .LGTMs $tbl.Assignable}}<br /><span style="font-size: smaller;">LGTMs: {{.LGTMHTML}}</span>{{end}}
-      {{if and .NotLGTMs $tbl.Assignable}}<br /><span style="font-size: smaller; color: #f74545;">NOT LGTMs: {{.NotLGTMHTML}}</span>{{end}}
-      {{if .LastUpdateBy}}<br /><span style="font-size: smaller; color: #777777;">(<span title="{{.LastUpdateBy}}">{{.LastUpdateBy | shortemail}}</span>) {{.LastUpdate}}</span>{{end}}
-    </td>
-    <td title="Last modified">{{.ModifiedAgo}}</td>
-    <td>{{if $.IsAdmin}}<a href="/update-cl?cl={{.Number}}" title="Update this CL">&#x27f3;</a>{{end}}</td>
-  </tr>
-{{end}}
-{{else}}
-<tr><td colspan="5"><em>none</em></td></tr>
-{{end}}
-{{end}}
-</table>
-
-<hr />
-<address>
-You are <span class="email">{{.User}}</span> &middot; <a href="{{.LogoutURL}}">logout</a><br />
-datastore timing: {{range .Timing}} {{.}}{{end}}
-</address>
-
-  </body>
-</html>
-`))
diff --git a/misc/dashboard/codereview/dashboard/gc.go b/misc/dashboard/codereview/dashboard/gc.go
deleted file mode 100644 (file)
index a80b375..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2012 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 dashboard
-
-// This file handles garbage collection of old CLs.
-
-import (
-       "net/http"
-       "time"
-
-       "appengine"
-       "appengine/datastore"
-)
-
-func init() {
-       http.HandleFunc("/gc", handleGC)
-}
-
-func handleGC(w http.ResponseWriter, r *http.Request) {
-       c := appengine.NewContext(r)
-
-       // Delete closed CLs that haven't been modified in 168 hours (7 days).
-       cutoff := time.Now().Add(-168 * time.Hour)
-       q := datastore.NewQuery("CL").
-               Filter("Closed =", true).
-               Filter("Modified <", cutoff).
-               Limit(100).
-               KeysOnly()
-       keys, err := q.GetAll(c, nil)
-       if err != nil {
-               c.Errorf("GetAll failed for old CLs: %v", err)
-               http.Error(w, err.Error(), http.StatusInternalServerError)
-               return
-       }
-       if len(keys) == 0 {
-               return
-       }
-
-       if err := datastore.DeleteMulti(c, keys); err != nil {
-               c.Errorf("DeleteMulti failed for old CLs: %v", err)
-               http.Error(w, err.Error(), http.StatusInternalServerError)
-               return
-       }
-       c.Infof("Deleted %d old CLs", len(keys))
-}
diff --git a/misc/dashboard/codereview/dashboard/mail.go b/misc/dashboard/codereview/dashboard/mail.go
deleted file mode 100644 (file)
index 838d082..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2012 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 dashboard
-
-// This file handles receiving mail.
-
-import (
-       "net/http"
-       "net/mail"
-       "regexp"
-       "time"
-
-       "appengine"
-       "appengine/datastore"
-)
-
-func init() {
-       http.HandleFunc("/_ah/mail/", handleMail)
-}
-
-var subjectRegexp = regexp.MustCompile(`.*code review (\d+):.*`)
-
-func handleMail(w http.ResponseWriter, r *http.Request) {
-       c := appengine.NewContext(r)
-
-       defer r.Body.Close()
-       msg, err := mail.ReadMessage(r.Body)
-       if err != nil {
-               c.Errorf("mail.ReadMessage: %v", err)
-               return
-       }
-
-       subj := msg.Header.Get("Subject")
-       m := subjectRegexp.FindStringSubmatch(subj)
-       if len(m) != 2 {
-               c.Debugf("Subject %q did not match /%v/", subj, subjectRegexp)
-               return
-       }
-
-       c.Infof("Found issue %q", m[1])
-
-       // Track the MessageID.
-       key := datastore.NewKey(c, "CL", m[1], 0, nil)
-       err = datastore.RunInTransaction(c, func(c appengine.Context) error {
-               cl := new(CL)
-               err := datastore.Get(c, key, cl)
-               if err != nil && err != datastore.ErrNoSuchEntity {
-                       return err
-               }
-               if err == datastore.ErrNoSuchEntity {
-                       // Must set sentinel values for time.Time fields
-                       // if this is a new entity.
-                       cl.Created = time.Unix(0, 0)
-                       cl.Modified = time.Unix(0, 0)
-               }
-               cl.LastMessageID = msg.Header.Get("Message-ID")
-               _, err = datastore.Put(c, key, cl)
-               return err
-       }, nil)
-       if err != nil {
-               c.Errorf("datastore transaction failed: %v", err)
-       }
-
-       // Update the CL after a delay to give Rietveld a chance to catch up.
-       UpdateCLLater(c, m[1], 10*time.Second)
-}
diff --git a/misc/dashboard/codereview/dashboard/people.go b/misc/dashboard/codereview/dashboard/people.go
deleted file mode 100644 (file)
index 7bab253..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2012 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 dashboard
-
-// This file handles identities of people.
-
-import (
-       "sort"
-)
-
-var (
-       emailToPerson  = make(map[string]string) // email => person
-       preferredEmail = make(map[string]string) // person => email
-       personList     []string
-)
-
-func init() {
-       // People we assume have golang.org and google.com accounts,
-       // and prefer to use their golang.org address for code review.
-       gophers := [...]string{
-               "adg",
-               "agl",
-               "bradfitz",
-               "campoy",
-               "cshapiro",
-               "dsymonds",
-               "gri",
-               "iant",
-               "khr",
-               "mpvl",
-               "nigeltao",
-               "r",
-               "rsc",
-               "sameer",
-       }
-       for _, p := range gophers {
-               personList = append(personList, p)
-               emailToPerson[p+"@golang.org"] = p
-               emailToPerson[p+"@google.com"] = p
-               preferredEmail[p] = p + "@golang.org"
-       }
-       // Other people.
-       others := map[string]string{
-               "adonovan": "adonovan@google.com",
-               "brainman": "alex.brainman@gmail.com",
-               "ality":    "ality@pbrane.org",
-               "dfc":      "dave@cheney.net",
-               "dvyukov":  "dvyukov@google.com",
-               "gustavo":  "gustavo@niemeyer.net",
-               "jsing":    "jsing@google.com",
-               "mikio":    "mikioh.mikioh@gmail.com",
-               "minux":    "minux.ma@gmail.com",
-               "remy":     "remyoudompheng@gmail.com",
-               "rminnich": "rminnich@gmail.com",
-       }
-       for p, e := range others {
-               personList = append(personList, p)
-               emailToPerson[e] = p
-               preferredEmail[p] = e
-       }
-
-       sort.Strings(personList)
-}
diff --git a/misc/dashboard/codereview/index.yaml b/misc/dashboard/codereview/index.yaml
deleted file mode 100644 (file)
index a87073c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-indexes:
-
-- kind: CL
-  properties:
-  - name: Author
-  - name: Modified
-    direction: desc
-
-- kind: CL
-  properties:
-  - name: Owner
-  - name: Modified
-    direction: desc
-
-- kind: CL
-  properties:
-  - name: Closed
-  - name: Modified
-    direction: desc
-
-- kind: CL
-  properties:
-  - name: Reviewer
-  - name: Modified
-    direction: desc
diff --git a/misc/dashboard/codereview/queue.yaml b/misc/dashboard/codereview/queue.yaml
deleted file mode 100644 (file)
index 1a35fac..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-queue:
-- name: update-cl
-  rate: 12/m
-  bucket_size: 1
diff --git a/misc/dashboard/codereview/static/gopherstamp.jpg b/misc/dashboard/codereview/static/gopherstamp.jpg
deleted file mode 100644 (file)
index b17f3c8..0000000
Binary files a/misc/dashboard/codereview/static/gopherstamp.jpg and /dev/null differ
diff --git a/misc/dashboard/codereview/static/icon.png b/misc/dashboard/codereview/static/icon.png
deleted file mode 100644 (file)
index c929ac8..0000000
Binary files a/misc/dashboard/codereview/static/icon.png and /dev/null differ