about summary refs log tree commit diff
path: root/gerrit/client.go
blob: c65b5016c1ff17c8a1c6531fba5bbc6a1e0c813f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package gerrit

import (
	goGerrit "github.com/andygrunwald/go-gerrit"

	"net/url"
)

// passed to gerrit when retrieving changesets
var additionalFields = []string{"LABELS", "CURRENT_REVISION", "CURRENT_COMMIT", "DETAILED_ACCOUNTS"}

// IClient defines the gerrit.Client interface
type IClient interface {
	SearchChangesets(queryString string) (changesets []*Changeset, Error error)
	GetHEAD(projectName string, branchName string) (string, error)
	GetChangeset(changeID string) (*Changeset, error)
	SubmitChangeset(changeset *Changeset) (*Changeset, error)
	RebaseChangeset(changeset *Changeset, ref string) (*Changeset, error)
	RemoveTag(changeset *Changeset, tag string) (*Changeset, error)
	GetBaseURL() string
}

var _ IClient = &Client{}

// Client provides some ways to interact with a gerrit instance
type Client struct {
	client  *goGerrit.Client
	baseURL string
}

// NewClient initializes a new gerrit client
func NewClient(URL, username, password string) (*Client, error) {
	urlParsed, err := url.Parse(URL)
	if err != nil {
		return nil, err
	}
	urlParsed.User = url.UserPassword(username, password)

	goGerritClient, err := goGerrit.NewClient(urlParsed.String(), nil)
	if err != nil {
		return nil, err
	}
	return &Client{
		client:  goGerritClient,
		baseURL: URL,
	}, nil
}

// SearchChangesets fetches a list of changesets matching a passed query string
func (gerrit *Client) SearchChangesets(queryString string) (changesets []*Changeset, Error error) {
	opt := &goGerrit.QueryChangeOptions{}
	opt.Query = []string{
		queryString,
	}
	opt.AdditionalFields = additionalFields //TODO: check DETAILED_ACCOUNTS is needed
	changes, _, err := gerrit.client.Changes.QueryChanges(opt)
	if err != nil {
		return nil, err
	}

	changesets = make([]*Changeset, 0)
	for _, change := range *changes {
		changesets = append(changesets, MakeChangeset(&change))
	}

	return changesets, nil
}

// GetHEAD returns the commit ID of a selected branch
func (gerrit *Client) GetHEAD(projectName string, branchName string) (string, error) {
	branchInfo, _, err := gerrit.client.Projects.GetBranch(projectName, branchName)
	if err != nil {
		return "", err
	}
	return branchInfo.Revision, nil
}

// GetChangeset downloads an existing Changeset from gerrit, by its ID
// Gerrit's API is a bit sparse, and only returns what you explicitly ask it
// This is used to refresh an existing changeset with more data.
func (gerrit *Client) GetChangeset(changeID string) (*Changeset, error) {
	opt := goGerrit.ChangeOptions{}
	opt.AdditionalFields = []string{"LABELS", "DETAILED_ACCOUNTS"}
	changeInfo, _, err := gerrit.client.Changes.GetChange(changeID, &opt)
	if err != nil {
		return nil, err
	}
	return MakeChangeset(changeInfo), nil
}

// SubmitChangeset submits a given changeset, and returns a changeset afterwards.
func (gerrit *Client) SubmitChangeset(changeset *Changeset) (*Changeset, error) {
	changeInfo, _, err := gerrit.client.Changes.SubmitChange(changeset.ChangeID, &goGerrit.SubmitInput{})
	if err != nil {
		return nil, err
	}
	return gerrit.GetChangeset(changeInfo.ChangeID)
}

// RebaseChangeset rebases a given changeset on top of a given ref
func (gerrit *Client) RebaseChangeset(changeset *Changeset, ref string) (*Changeset, error) {
	changeInfo, _, err := gerrit.client.Changes.RebaseChange(changeset.ChangeID, &goGerrit.RebaseInput{
		Base: ref,
	})
	if err != nil {
		return changeset, err
	}
	return gerrit.GetChangeset(changeInfo.ChangeID)
}

// RemoveTag removes the submit queue tag from a changeset and updates gerrit
// we never add, that's something users should do in the GUI.
func (gerrit *Client) RemoveTag(changeset *Changeset, tag string) (*Changeset, error) {
	hashTags := changeset.HashTags
	newHashTags := []string{}
	for _, hashTag := range hashTags {
		if hashTag != tag {
			newHashTags = append(newHashTags, hashTag)
		}
	}
	// TODO: implement set hashtags api in go-gerrit and use here
	// https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#set-hashtags
	return changeset, nil
}

// GetBaseURL returns the gerrit base URL
func (gerrit *Client) GetBaseURL() string {
	return gerrit.baseURL
}