diff options
Diffstat (limited to 'gerrit/client.go')
-rw-r--r-- | gerrit/client.go | 173 |
1 files changed, 139 insertions, 34 deletions
diff --git a/gerrit/client.go b/gerrit/client.go index c65b5016c1ff..fd8a244151ab 100644 --- a/gerrit/client.go +++ b/gerrit/client.go @@ -1,35 +1,52 @@ package gerrit import ( + "fmt" + goGerrit "github.com/andygrunwald/go-gerrit" + "github.com/apex/log" "net/url" ) // passed to gerrit when retrieving changesets -var additionalFields = []string{"LABELS", "CURRENT_REVISION", "CURRENT_COMMIT", "DETAILED_ACCOUNTS"} +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) + Refresh() error + GetHEAD() string + GetBaseURL() string + GetChangesetURL(changeset *Changeset) string SubmitChangeset(changeset *Changeset) (*Changeset, error) RebaseChangeset(changeset *Changeset, ref string) (*Changeset, error) RemoveTag(changeset *Changeset, tag string) (*Changeset, error) - GetBaseURL() string + ChangesetIsRebasedOnHEAD(changeset *Changeset) bool + SerieIsRebasedOnHEAD(serie *Serie) bool + FilterSeries(filter func(s *Serie) bool) []*Serie + FindSerie(filter func(s *Serie) bool) *Serie } var _ IClient = &Client{} // Client provides some ways to interact with a gerrit instance type Client struct { - client *goGerrit.Client - baseURL string + client *goGerrit.Client + logger *log.Logger + baseURL string + projectName string + branchName string + series []*Serie + head string } // NewClient initializes a new gerrit client -func NewClient(URL, username, password string) (*Client, error) { +func NewClient(logger *log.Logger, URL, username, password, projectName, branchName string) (*Client, error) { urlParsed, err := url.Parse(URL) if err != nil { return nil, err @@ -43,17 +60,58 @@ func NewClient(URL, username, password string) (*Client, error) { return &Client{ client: goGerritClient, baseURL: URL, + logger: logger, }, nil } -// SearchChangesets fetches a list of changesets matching a passed query string -func (gerrit *Client) SearchChangesets(queryString string) (changesets []*Changeset, Error error) { +// refreshHEAD queries the commit ID of the selected project and branch +func (c *Client) refreshHEAD() (string, error) { + branchInfo, _, err := c.client.Projects.GetBranch(c.projectName, c.branchName) + if err != nil { + return "", err + } + return branchInfo.Revision, nil +} + +// GetHEAD returns the internally stored HEAD +func (c *Client) GetHEAD() string { + return c.head +} + +// Refresh causes the client to refresh internal view of gerrit +func (c *Client) Refresh() error { + c.logger.Debug("refreshing from gerrit") + HEAD, err := c.refreshHEAD() + if err != nil { + return err + } + c.head = HEAD + + var queryString = fmt.Sprintf("status:open project:%s branch:%s", c.projectName, c.branchName) + c.logger.Debugf("fetching changesets: %s", queryString) + changesets, err := c.fetchChangesets(queryString) + if err != nil { + return err + } + + c.logger.Warnf("assembling series…") + series, err := AssembleSeries(changesets, c.logger) + if err != nil { + return err + } + series = SortSeries(series) + c.series = series + return nil +} + +// fetchChangesets fetches a list of changesets matching a passed query string +func (c *Client) fetchChangesets(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) + opt.AdditionalFields = additionalFields + changes, _, err := c.client.Changes.QueryChanges(opt) if err != nil { return nil, err } @@ -66,22 +124,13 @@ func (gerrit *Client) SearchChangesets(queryString string) (changesets []*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 +// fetchChangeset 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) { +func (c *Client) fetchChangeset(changeID string) (*Changeset, error) { opt := goGerrit.ChangeOptions{} opt.AdditionalFields = []string{"LABELS", "DETAILED_ACCOUNTS"} - changeInfo, _, err := gerrit.client.Changes.GetChange(changeID, &opt) + changeInfo, _, err := c.client.Changes.GetChange(changeID, &opt) if err != nil { return nil, err } @@ -89,28 +138,30 @@ func (gerrit *Client) GetChangeset(changeID string) (*Changeset, error) { } // 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{}) +// TODO: update HEAD +func (c *Client) SubmitChangeset(changeset *Changeset) (*Changeset, error) { + changeInfo, _, err := c.client.Changes.SubmitChange(changeset.ChangeID, &goGerrit.SubmitInput{}) if err != nil { return nil, err } - return gerrit.GetChangeset(changeInfo.ChangeID) + return c.fetchChangeset(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{ +// TODO: update HEAD +func (c *Client) RebaseChangeset(changeset *Changeset, ref string) (*Changeset, error) { + changeInfo, _, err := c.client.Changes.RebaseChange(changeset.ChangeID, &goGerrit.RebaseInput{ Base: ref, }) if err != nil { return changeset, err } - return gerrit.GetChangeset(changeInfo.ChangeID) + return c.fetchChangeset(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) { +func (c *Client) RemoveTag(changeset *Changeset, tag string) (*Changeset, error) { hashTags := changeset.HashTags newHashTags := []string{} for _, hashTag := range hashTags { @@ -118,12 +169,66 @@ func (gerrit *Client) RemoveTag(changeset *Changeset, tag string) (*Changeset, e newHashTags = append(newHashTags, hashTag) } } - // TODO: implement set hashtags api in go-gerrit and use here + // TODO: implement setting 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 +func (c *Client) GetBaseURL() string { + return c.baseURL +} + +// GetProjectName returns the configured gerrit project name +func (c *Client) GetProjectName() string { + return c.projectName +} + +// GetBranchName returns the configured gerrit branch name +func (c *Client) GetBranchName() string { + return c.branchName +} + +// GetChangesetURL returns the URL to view a given changeset +func (c *Client) GetChangesetURL(changeset *Changeset) string { + return fmt.Sprintf("%s/c/%s/+/%d", c.GetBaseURL(), c.projectName, changeset.Number) +} + +// ChangesetIsRebasedOnHEAD returns true if the changeset is rebased on the current HEAD +func (c *Client) ChangesetIsRebasedOnHEAD(changeset *Changeset) bool { + if len(changeset.ParentCommitIDs) != 1 { + return false + } + return changeset.ParentCommitIDs[0] == c.head +} + +// SerieIsRebasedOnHEAD returns true if the whole series is rebased on the current HEAD +// this is already the case if the first changeset in the series is rebased on the current HEAD +func (c *Client) SerieIsRebasedOnHEAD(serie *Serie) bool { + // an empty serie should not exist + if len(serie.ChangeSets) == 0 { + return false + } + return c.ChangesetIsRebasedOnHEAD(serie.ChangeSets[0]) +} + +// FilterSeries returns a subset of all Series, passing the given filter function +func (c *Client) FilterSeries(filter func(s *Serie) bool) []*Serie { + matchedSeries := []*Serie{} + for _, serie := range c.series { + if filter(serie) { + matchedSeries = append(matchedSeries, serie) + } + } + return matchedSeries +} + +// FindSerie returns the first serie that matches the filter, or nil if none was found +func (c *Client) FindSerie(filter func(s *Serie) bool) *Serie { + for _, serie := range c.series { + if filter(serie) { + return serie + } + } + return nil } |