cmd/checker: use query by scheme
Previously, we would get a list of checkers on startup, so newly
added checkers would never be detected by Gerrit. The per-scheme
query lets the linter pick up new checkers on the fly.
Change-Id: I2a0b5127494726c9fdb499ab912e475721cbf5bd
diff --git a/cmd/checker/checker.go b/cmd/checker/checker.go
index 4cfc13f..f57ebc7 100644
--- a/cmd/checker/checker.go
+++ b/cmd/checker/checker.go
@@ -34,13 +34,10 @@
type gerritChecker struct {
server *gerrit.Server
- // UUID => language
- checkerUUIDs []string
-
todo chan *gerrit.PendingChecksInfo
}
-const checkerScheme = "fmt:"
+const checkerScheme = "fmt"
// ListCheckers returns all the checkers that conform to our scheme.
func (gc *gerritChecker) ListCheckers() ([]*gerrit.CheckerInfo, error) {
@@ -56,7 +53,7 @@
filtered := out[:0]
for _, o := range out {
- if !strings.HasPrefix(o.UUID, checkerScheme) {
+ if !strings.HasPrefix(o.UUID, checkerScheme+":") {
continue
}
if _, ok := checkerLanguage(o.UUID); !ok {
@@ -73,7 +70,7 @@
hash := sha1.New()
hash.Write([]byte(repo))
- uuid := fmt.Sprintf("%s%s-%x", checkerScheme, language, hash.Sum(nil))
+ uuid := fmt.Sprintf("%s:%s-%x", checkerScheme, language, hash.Sum(nil))
in := gerrit.CheckerInput{
UUID: uuid,
Name: language + " formatting",
@@ -106,7 +103,7 @@
}
func checkerLanguage(uuid string) (string, bool) {
- uuid = strings.TrimPrefix(uuid, checkerScheme)
+ uuid = strings.TrimPrefix(uuid, checkerScheme+":")
fields := strings.Split(uuid, "-")
if len(fields) != 2 {
return "", false
@@ -120,14 +117,6 @@
todo: make(chan *gerrit.PendingChecksInfo, 5),
}
- if out, err := gc.ListCheckers(); err != nil {
- return nil, err
- } else {
- for _, checker := range out {
- gc.checkerUUIDs = append(gc.checkerUUIDs, checker.UUID)
- }
- }
-
go gc.pendingLoop()
return gc, nil
}
@@ -192,22 +181,20 @@
func (c *gerritChecker) pendingLoop() {
for {
- for _, uuid := range c.checkerUUIDs {
- pending, err := c.server.PendingChecks(uuid)
- if err != nil {
- log.Printf("PendingChecks: %v", err)
- continue
- }
- if len(pending) == 0 {
- log.Printf("no pending checks")
- }
+ pending, err := c.server.PendingChecksByScheme(checkerScheme)
+ if err != nil {
+ log.Printf("PendingChecksByScheme: %v", err)
+ continue
+ }
+ if len(pending) == 0 {
+ log.Printf("no pending checks")
+ }
- for _, pc := range pending {
- select {
- case c.todo <- pc:
- default:
- log.Println("too busy; dropping pending check.")
- }
+ for _, pc := range pending {
+ select {
+ case c.todo <- pc:
+ default:
+ log.Println("too busy; dropping pending check.")
}
}
// TODO: real rate limiting.
@@ -274,7 +261,7 @@
status = statusIrrelevant
} else if err != nil {
status = statusFail
- log.Printf("checkChange(%s, %d, %q): %v", changeID, psID, lang)
+ log.Printf("checkChange(%s, %d, %q): %v", changeID, psID, lang, err)
msgs = []string{fmt.Sprintf("tool failure: %v", err)}
} else if len(msgs) == 0 {
status = statusSuccessful
diff --git a/gerrit/server.go b/gerrit/server.go
index e23200b..5072eb1 100644
--- a/gerrit/server.go
+++ b/gerrit/server.go
@@ -165,6 +165,27 @@
return &Change{files}, nil
}
+func (s *Server) PendingChecksByScheme(scheme string) ([]*PendingChecksInfo, error) {
+ u := s.URL
+
+ // The trailing '/' handling is really annoying.
+ u.Path = path.Join(u.Path, "a/plugins/checks/checks.pending/") + "/"
+
+ q := "scheme:" + scheme
+ u.RawQuery = "query=" + q
+ content, err := s.Get(&u)
+ if err != nil {
+ return nil, err
+ }
+
+ var out []*PendingChecksInfo
+ if err := Unmarshal(content, &out); err != nil {
+ return nil, err
+ }
+
+ return out, nil
+}
+
func (s *Server) PendingChecks(checkerUUID string) ([]*PendingChecksInfo, error) {
u := s.URL