Skip to content

Commit

Permalink
x/build/gerrit: add support for querying accounts in Gerrit
Browse files Browse the repository at this point in the history
Added support for querying accounts in Gerrit. This is a pre-requisite
for golang/go#21216

Change-Id: Ic6776ddf18a23e347d0eb7edf91a934d2feb01c9
Reviewed-on: https://go-review.googlesource.com/61970
Reviewed-by: Kevin Burke <kev@inburke.com>
  • Loading branch information
judepereira authored and kevinburke committed Sep 7, 2017
1 parent 031ab4e commit ec36dd2
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
49 changes: 49 additions & 0 deletions gerrit/gerrit.go
Expand Up @@ -210,11 +210,19 @@ type ChangeInfo struct {
MoreChanges bool `json:"_more_changes"`
}

// AccountInfo is a Gerrit data structure. It's used both for getting the details
// for a single account, as well as for querying multiple accounts.
type AccountInfo struct {
NumericID int64 `json:"_account_id"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Username string `json:"username,omitempty"`

// MoreAccounts is set on the last account from QueryAccounts if
// the result set is truncated by an 'n' parameter (or has more).
MoreAccounts bool `json:"_more_accounts"`

// TODO: "avatars" is also returned, but not added here yet (add if required)
}

func (ai *AccountInfo) Equal(v *AccountInfo) bool {
Expand Down Expand Up @@ -550,6 +558,47 @@ func (c *Client) GetAccountInfo(ctx context.Context, accountID string) (AccountI
return res, err
}

// QueryAccountsOpt are options for QueryAccounts.
type QueryAccountsOpt struct {
// N is the number of results to return.
// If 0, the 'n' parameter is not sent to Gerrit.
N int

// Start is the number of results to skip (useful in pagination).
// To figure out if there are more results, the last AccountInfo struct
// in the last call to QueryAccounts will have the field MoreAccounts=true.
// If 0, the 'S' parameter is not sent to Gerrit.
Start int

// Fields are optional fields to also return.
// Example strings include "DETAILS", "ALL_EMAILS".
// By default, only the account IDs are returned.
// For a complete list, see:
// https://gerrit-review.googlesource.com/Documentation/rest-api-accounts.html#query-account
Fields []string
}

// QueryAccounts queries accounts. The q parameter is a Gerrit search query.
// For the API call and query syntax, see https://gerrit-review.googlesource.com/Documentation/rest-api-accounts.html#query-account
func (c *Client) QueryAccounts(ctx context.Context, q string, opts ...QueryAccountsOpt) ([]*AccountInfo, error) {
var opt QueryAccountsOpt
switch len(opts) {
case 0:
case 1:
opt = opts[0]
default:
return nil, errors.New("only 1 option struct supported")
}
var changes []*AccountInfo
err := c.do(ctx, &changes, "GET", "/accounts/", urlValues{
"q": {q},
"n": condInt(opt.N),
"o": opt.Fields,
"S": condInt(opt.Start),
})
return changes, err
}

// GetProjects returns a map of all projects on the Gerrit server.
func (c *Client) GetProjects(ctx context.Context, branch string) (map[string]*ProjectInfo, error) {
mp := make(map[string]*ProjectInfo)
Expand Down
58 changes: 58 additions & 0 deletions gerrit/gerrit_test.go
Expand Up @@ -178,6 +178,64 @@ func TestGetChangeError(t *testing.T) {
}
}

var queryAccountsResponse = []byte(`)]}'
[
{
"_account_id": 1,
"name": "John Doe",
"email": "john@doe.com"
},
{
"_account_id": 2,
"name": "Jane Doe",
"email": "jane@doe.com",
"_more_accounts": true
}
]`)

func TestQueryAccounts(t *testing.T) {
hitServer := false
uri := ""

s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hitServer = true
uri = r.URL.RequestURI()
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(200)
w.Write(queryAccountsResponse)
}))
defer s.Close()
c := NewClient(s.URL, NoAuth)
info, err := c.QueryAccounts(context.Background(), "is:active", QueryAccountsOpt{
Fields: []string{"DETAILS"},
N: 2,
})
if err != nil {
t.Fatal(err.Error())
}
if !hitServer {
t.Errorf("expected to hit test server, didn't")
}
if want := "/accounts/?n=2&o=DETAILS&q=is%3Aactive"; uri != want {
t.Errorf("expected RequestURI to be %q, got %q", want, uri)
}
if len(info) != 2 {
t.Errorf("expected accounts length to be 2, got %d", len(info))
}
if info[0].NumericID != 1 || info[0].Name != "John Doe" || info[0].Email != "john@doe.com" {
t.Errorf("expected to match John Doe in account, got %s", info[0])
}
if info[1].NumericID != 2 || info[1].Name != "Jane Doe" || info[1].Email != "jane@doe.com" {
t.Errorf("expected to match Jane Doe in account, got %s", info[1])
}
if info[0].MoreAccounts {
t.Errorf("expected to MoreAccounts to be false for John Doe")
}
if !info[1].MoreAccounts {
t.Errorf("expected to MoreAccounts to be true for Jane Doe")
}
}

func TestTimeStampMarshalJson(t *testing.T) {
ts := TimeStamp(time.Date(1888, 6, 24, 6, 8, 30, 123456789, time.FixedZone("+1", 3600)))
b, err := ts.MarshalJSON()
Expand Down

0 comments on commit ec36dd2

Please sign in to comment.