dmitri.shuralyov.com/service/change/...

gerritapi: add support for labels via Gerrit CL hashtags

It's helpful to visualize hashtags applied to CLs.
Do so by mapping them to labels.
dmitshur committed 5 years ago commit a289f548ed13ec8989f684f2d1a0e2ad2db411d8
Collapse all
gerritapi/gerritapi.go
@@ -2,20 +2,22 @@
package gerritapi

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"sort"
	"strconv"
	"strings"
	"unicode"

	"dmitri.shuralyov.com/service/change"
	"dmitri.shuralyov.com/state"
	"github.com/andygrunwald/go-gerrit"
	"github.com/shurcooL/issues"
	"github.com/shurcooL/users"
)

// NewService creates a Gerrit-backed issues.Service using given Gerrit client.
// client must be non-nil.
@@ -61,14 +63,22 @@ func (s service) List(ctx context.Context, repo string, opt change.ListOptions)
	var is []change.Change
	for _, chg := range *cs {
		if chg.Status == "DRAFT" {
			continue
		}
		var labels []issues.Label
		for _, hashtag := range chg.Hashtags {
			labels = append(labels, issues.Label{
				Name:  hashtag,
				Color: issues.RGB{R: 0xed, G: 0xed, B: 0xed}, // A default light gray.
			})
		}
		is = append(is, change.Change{
			ID:        uint64(chg.Number),
			State:     changeState(chg.Status),
			Title:     chg.Subject,
			Labels:    labels,
			Author:    s.gerritUser(chg.Owner),
			CreatedAt: chg.Created.Time,
			Replies:   len(chg.Messages),
		})
	}
@@ -96,14 +106,22 @@ func (s service) Get(ctx context.Context, repo string, id uint64) (change.Change
		return change.Change{}, err
	}
	if chg.Status == "DRAFT" {
		return change.Change{}, os.ErrNotExist
	}
	var labels []issues.Label
	for _, hashtag := range chg.Hashtags {
		labels = append(labels, issues.Label{
			Name:  hashtag,
			Color: issues.RGB{R: 0xed, G: 0xed, B: 0xed}, // A default light gray.
		})
	}
	return change.Change{
		ID:           id,
		State:        changeState(chg.Status),
		Title:        chg.Subject,
		Labels:       labels,
		Author:       s.gerritUser(chg.Owner),
		CreatedAt:    chg.Created.Time,
		Replies:      len(chg.Messages),
		Commits:      len(chg.Revisions),
		ChangedFiles: 0, // TODO.
@@ -283,10 +301,11 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt *
		Body:      commitMessageBody(commit.Message),
		Editable:  false,
	})
	for idx, message := range chg.Messages {
		if strings.HasPrefix(message.Tag, "autogenerated:") {
		Outer:
			switch message.Tag[len("autogenerated:"):] {
			case "gerrit:merged":
				timeline = append(timeline, change.TimelineItem{
					Actor:     s.gerritUser(message.Author),
					CreatedAt: message.Date.Time,
@@ -346,10 +365,38 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt *
				timeline = append(timeline, change.TimelineItem{
					Actor:     s.gerritUser(message.Author),
					CreatedAt: message.Date.Time,
					Payload:   change.ReopenedEvent{},
				})
			case "gerrit:setHashtag":
				var payload interface{} // One of change.LabeledEvent or change.UnlabeledEvent.
				switch {
				case strings.HasPrefix(message.Message, "Hashtag added: "):
					hashtag := message.Message[len("Hashtag added: "):]
					payload = change.LabeledEvent{
						Label: issues.Label{
							Name:  hashtag,
							Color: issues.RGB{R: 0xed, G: 0xed, B: 0xed}, // A default light gray.
						},
					}
				case strings.HasPrefix(message.Message, "Hashtag removed: "):
					hashtag := message.Message[len("Hashtag removed: "):]
					payload = change.UnlabeledEvent{
						Label: issues.Label{
							Name:  hashtag,
							Color: issues.RGB{R: 0xed, G: 0xed, B: 0xed}, // A default light gray.
						},
					}
				default:
					log.Printf("unknown setHashtag message: %q", message.Message)
					break Outer
				}
				timeline = append(timeline, change.TimelineItem{
					Actor:     s.gerritUser(message.Author),
					CreatedAt: message.Date.Time,
					Payload:   payload,
				})
			}
			continue
		}
		labels, body, ok := parseMessage(message.Message)
		if !ok {