@@ -8,10 +8,11 @@ import ( "net/http" "os" "sort" "strconv" "strings" "time" "unicode" "dmitri.shuralyov.com/service/change" "dmitri.shuralyov.com/state" "github.com/andygrunwald/go-gerrit" @@ -299,11 +300,12 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt * User: s.gerritUser(chg.Owner), CreatedAt: chg.Created.Time, Body: commitMessageBody(commit.Message), Editable: false, }) var mergedRevisionSHA string // Set to merged revision SHA when a change.MergedEvent event is encountered. var mergedRevisionSHA string // Set to merged revision SHA when a change.MergedEvent event is encountered. var labelChanges = make(map[time.Time]int) // Map of times when a label was changed by someone. Time -> AccountID. for idx, message := range chg.Messages { if strings.HasPrefix(message.Tag, "autogenerated:") { Outer: switch message.Tag[len("autogenerated:"):] { case "gerrit:merged": @@ -408,10 +410,13 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt * } labels, body, ok := parseMessage(message.Message) if !ok { continue } if labels != "" { labelChanges[message.Date.Time] = message.Author.AccountID } var cs []change.InlineComment for file, comments := range *comments { for _, c := range comments { if c.Updated.Equal(message.Date.Time) { cs = append(cs, change.InlineComment{ @@ -456,10 +461,42 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt * SHA: sha, Subject: fmt.Sprintf("Patch Set %d", r.Number), }, }) } var reviewers = make(map[int]struct{}) // Set of reviewers during ReviewerUpdates iteration. Key is AccountID. for _, ru := range chg.ReviewerUpdates { switch ru.State { case "REVIEWER": reviewers[ru.Reviewer.AccountID] = struct{}{} if ru.UpdatedBy.AccountID == ru.Reviewer.AccountID && labelChanges[ru.Updated.Time] == ru.UpdatedBy.AccountID { // Skip because it was an implicit add-self-reviewer due to label change. continue } timeline = append(timeline, change.TimelineItem{ Actor: s.gerritUser(ru.UpdatedBy), CreatedAt: ru.Updated.Time, Payload: change.ReviewRequestedEvent{ RequestedReviewer: s.gerritUser(ru.Reviewer), }, }) case "CC", "REMOVED": if _, ok := reviewers[ru.Reviewer.AccountID]; !ok { // Skip because they weren't a reviewer. continue } delete(reviewers, ru.Reviewer.AccountID) timeline = append(timeline, change.TimelineItem{ Actor: s.gerritUser(ru.UpdatedBy), CreatedAt: ru.Updated.Time, Payload: change.ReviewRequestRemovedEvent{ RequestedReviewer: s.gerritUser(ru.Reviewer), }, }) } } return timeline, nil } func parseMessage(m string) (labels string, body string, ok bool) { // "Patch Set ".