aboutsummaryrefslogtreecommitdiff
path: root/git-codereview/api.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2017-10-02 09:42:13 -0400
committerRuss Cox <rsc@golang.org>2017-11-10 03:12:52 +0000
commit0bdc7edde01a92e96255c6845b536d59706b9542 (patch)
tree38e33d499a8dff245b9d3d7618c967260132a2fd /git-codereview/api.go
parentc4baf783371a7c2b30b95ab528a38f6b12e7b6c1 (diff)
downloadgo-x-review-0bdc7edde01a92e96255c6845b536d59706b9542.tar.xz
git-codereview: batch GerritChange info fetches during pending
This speeds pending a bit by reducing the number of round trips to the Gerrit server when you have a stack of CLs. Change-Id: I456e1a8739b9b6586f4e05c1a5442f402e440a79 Reviewed-on: https://go-review.googlesource.com/67571 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'git-codereview/api.go')
-rw-r--r--git-codereview/api.go59
1 files changed, 58 insertions, 1 deletions
diff --git a/git-codereview/api.go b/git-codereview/api.go
index a81fc9e..77d2c08 100644
--- a/git-codereview/api.go
+++ b/git-codereview/api.go
@@ -269,7 +269,7 @@ func gerritAPI(path string, requestBody []byte, target interface{}) error {
if target != nil {
i := bytes.IndexByte(body, '\n')
if i < 0 {
- return fmt.Errorf("%s: malformed json response", url)
+ return fmt.Errorf("%s: malformed json response - bad header", url)
}
body = body[i:]
if err := json.Unmarshal(body, target); err != nil {
@@ -302,6 +302,63 @@ func readGerritChange(changeID string) (*GerritChange, error) {
return &c, nil
}
+// readGerritChanges is like readGerritChange but expects changeID
+// to be a query parameter list like q=change:XXX&q=change:YYY&o=OPTIONS,
+// and it expects to receive a JSON array of GerritChanges, not just one.
+func readGerritChanges(query string) ([][]*GerritChange, error) {
+ // The Gerrit server imposes a limit of at most 10 q= parameters.
+ v, err := url.ParseQuery(query)
+ if err != nil {
+ return nil, err
+ }
+ var results []chan gerritChangeResult
+ for len(v["q"]) > 0 {
+ n := len(v["q"])
+ if n > 10 {
+ n = 10
+ }
+ all := v["q"]
+ v["q"] = all[:n]
+ query := v.Encode()
+ v["q"] = all[n:]
+ ch := make(chan gerritChangeResult, 1)
+ go readGerritChangesBatch(query, n, ch)
+ results = append(results, ch)
+ }
+
+ var c [][]*GerritChange
+ for _, ch := range results {
+ res := <-ch
+ if res.err != nil {
+ return nil, res.err
+ }
+ c = append(c, res.c...)
+ }
+ return c, nil
+}
+
+type gerritChangeResult struct {
+ c [][]*GerritChange
+ err error
+}
+
+func readGerritChangesBatch(query string, n int, ch chan gerritChangeResult) {
+ var c [][]*GerritChange
+ // If there are multiple q=, the server sends back an array of arrays of results.
+ // If there is a single q=, it only sends back an array of results; in that case
+ // we need to do the wrapping ourselves.
+ var arg interface{} = &c
+ if n == 1 {
+ c = append(c, nil)
+ arg = &c[0]
+ }
+ err := gerritAPI("/a/changes/?"+query, nil, arg)
+ if len(c) != n && err == nil {
+ err = fmt.Errorf("gerrit result count mismatch")
+ }
+ ch <- gerritChangeResult{c, err}
+}
+
// GerritChange is the JSON struct returned by a Gerrit CL query.
type GerritChange struct {
ID string