| package gerrit |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "io/ioutil" |
| "net/url" |
| "time" |
| ) |
| |
| // PatchSet contains detailed information about a specific patch set. |
| // |
| // Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/json.html#patchSet |
| type PatchSet struct { |
| Number Number `json:"number"` |
| Revision string `json:"revision"` |
| Parents []string `json:"parents"` |
| Ref string `json:"ref"` |
| Uploader AccountInfo `json:"uploader"` |
| Author AccountInfo `json:"author"` |
| CreatedOn int `json:"createdOn"` |
| IsDraft bool `json:"isDraft"` |
| Kind string `json:"kind"` |
| } |
| |
| // RefUpdate contains data about a reference update. |
| // |
| // Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/json.html#refUpdate |
| type RefUpdate struct { |
| OldRev string `json:"oldRev"` |
| NewRev string `json:"newRev"` |
| RefName string `json:"refName"` |
| Project string `json:"project"` |
| } |
| |
| // EventInfo contains information about an event emitted by Gerrit. This |
| // structure can be used either when parsing streamed events or when reading |
| // the output of the events-log plugin. |
| // |
| // Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.html#events |
| type EventInfo struct { |
| Type string `json:"type"` |
| Change ChangeInfo `json:"change,omitempty"` |
| ChangeKey ChangeInfo `json:"changeKey,omitempty"` |
| PatchSet PatchSet `json:"patchSet,omitempty"` |
| EventCreatedOn int `json:"eventCreatedOn,omitempty"` |
| Reason string `json:"reason,omitempty"` |
| Abandoner AccountInfo `json:"abandoner,omitempty"` |
| Restorer AccountInfo `json:"restorer,omitempty"` |
| Submitter AccountInfo `json:"submitter,omitempty"` |
| Author AccountInfo `json:"author,omitempty"` |
| Uploader AccountInfo `json:"uploader,omitempty"` |
| Approvals []AccountInfo `json:"approvals,omitempty"` |
| Comment string `json:"comment,omitempty"` |
| Editor AccountInfo `json:"editor,omitempty"` |
| Added []string `json:"added,omitempty"` |
| Removed []string `json:"removed,omitempty"` |
| Hashtags []string `json:"hashtags,omitempty"` |
| RefUpdate RefUpdate `json:"refUpdate,omitempty"` |
| Project ProjectInfo `json:"project,omitempty"` |
| Reviewer AccountInfo `json:"reviewer,omitempty"` |
| OldTopic string `json:"oldTopic,omitempty"` |
| Changer AccountInfo `json:"changer,omitempty"` |
| } |
| |
| // EventsLogService contains functions for querying the API provided |
| // by the optional events-log plugin. |
| type EventsLogService struct { |
| client *Client |
| } |
| |
| // EventsLogOptions contains options for querying events from the events-logs |
| // plugin. |
| type EventsLogOptions struct { |
| From time.Time |
| To time.Time |
| |
| // IgnoreUnmarshalErrors will cause GetEvents to ignore any errors |
| // that come up when calling json.Unmarshal. This can be useful in |
| // cases where the events-log plugin was not kept up to date with |
| // the Gerrit version for some reason. In these cases the events-log |
| // plugin will return data structs that don't match the EventInfo |
| // struct which in turn causes issues for json.Unmarshal. |
| IgnoreUnmarshalErrors bool |
| } |
| |
| // getURL returns the url that should be used in the request. This will vary |
| // depending on the options provided to GetEvents. |
| func (events *EventsLogService) getURL(options *EventsLogOptions) (string, error) { |
| parsed, err := url.Parse("/plugins/events-log/events/") |
| if err != nil { |
| return "", err |
| } |
| |
| query := parsed.Query() |
| |
| if !options.From.IsZero() { |
| query.Set("t1", options.From.Format("2006-01-02 15:04:05")) |
| } |
| |
| if !options.To.IsZero() { |
| query.Set("t2", options.To.Format("2006-01-02 15:04:05")) |
| } |
| |
| encoded := query.Encode() |
| if len(encoded) > 0 { |
| parsed.RawQuery = encoded |
| } |
| |
| return parsed.String(), nil |
| } |
| |
| // GetEvents returns a list of events for the given input options. Use of this |
| // function requires an authenticated user and for the events-log plugin to be |
| // installed. This function returns the unmarshalled EventInfo structs, response, |
| // failed lines and errors. Marshaling errors will cause this function to return |
| // before processing is complete unless you set EventsLogOptions.IgnoreUnmarshalErrors |
| // to true. This can be useful in cases where the events-log plugin got out of sync |
| // with the Gerrit version which in turn produced events which can't be transformed |
| // unmarshalled into EventInfo. |
| // |
| // Gerrit API docs: https://<yourserver>/plugins/events-log/Documentation/rest-api-events.html |
| func (events *EventsLogService) GetEvents(options *EventsLogOptions) ([]EventInfo, *Response, [][]byte, error) { |
| info := []EventInfo{} |
| failures := [][]byte{} |
| requestURL, err := events.getURL(options) |
| |
| if err != nil { |
| return info, nil, failures, err |
| } |
| |
| request, err := events.client.NewRequest("GET", requestURL, nil) |
| if err != nil { |
| return info, nil, failures, err |
| } |
| |
| // Perform the request but do not pass in a structure to unpack |
| // the response into. The format of the response is one EventInfo |
| // object per line so we need to manually handle the response here. |
| response, err := events.client.Do(request, nil) |
| if err != nil { |
| return info, response, failures, err |
| } |
| |
| body, err := ioutil.ReadAll(response.Body) |
| defer response.Body.Close() // nolint: errcheck |
| if err != nil { |
| return info, response, failures, err |
| } |
| |
| for _, line := range bytes.Split(body, []byte("\n")) { |
| if len(line) > 0 { |
| event := EventInfo{} |
| if err := json.Unmarshal(line, &event); err != nil { // nolint: vetshadow |
| failures = append(failures, line) |
| |
| if !options.IgnoreUnmarshalErrors { |
| return info, response, failures, err |
| } |
| continue |
| } |
| info = append(info, event) |
| } |
| } |
| return info, response, failures, err |
| } |