diff options
| author | Russ Cox <rsc@golang.org> | 2017-10-02 09:42:13 -0400 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2017-11-10 03:12:52 +0000 |
| commit | 0bdc7edde01a92e96255c6845b536d59706b9542 (patch) | |
| tree | 38e33d499a8dff245b9d3d7618c967260132a2fd /git-codereview/api.go | |
| parent | c4baf783371a7c2b30b95ab528a38f6b12e7b6c1 (diff) | |
| download | go-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.go | 59 |
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 |
