• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2021 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// gerrit provides helpers for obtaining information from Tint's gerrit instance
16package gerrit
17
18import (
19	"fmt"
20	"io/ioutil"
21	"os"
22	"regexp"
23	"strings"
24
25	"github.com/andygrunwald/go-gerrit"
26)
27
28const URL = "https://dawn-review.googlesource.com/"
29
30// G is the interface to gerrit
31type G struct {
32	client        *gerrit.Client
33	authenticated bool
34}
35
36type Config struct {
37	Username string
38	Password string
39}
40
41func LoadCredentials() (user, pass string) {
42	cookiesFile := os.Getenv("HOME") + "/.gitcookies"
43	if cookies, err := ioutil.ReadFile(cookiesFile); err == nil {
44		re := regexp.MustCompile(`dawn-review.googlesource.com\s+(?:FALSE|TRUE)[\s/]+(?:FALSE|TRUE)\s+[0-9]+\s+.\s+(.*)=(.*)`)
45		match := re.FindStringSubmatch(string(cookies))
46		if len(match) == 3 {
47			return match[1], match[2]
48		}
49	}
50	return "", ""
51}
52
53func New(cfg Config) (*G, error) {
54	client, err := gerrit.NewClient(URL, nil)
55	if err != nil {
56		return nil, fmt.Errorf("couldn't create gerrit client: %w", err)
57	}
58
59	user, pass := cfg.Username, cfg.Password
60	if user == "" {
61		user, pass = LoadCredentials()
62	}
63
64	if user != "" {
65		client.Authentication.SetBasicAuth(user, pass)
66	}
67
68	return &G{client, user != ""}, nil
69}
70
71func (g *G) QueryChanges(queryParts ...string) (changes []gerrit.ChangeInfo, query string, err error) {
72	changes = []gerrit.ChangeInfo{}
73	query = strings.Join(queryParts, "+")
74	for {
75		batch, _, err := g.client.Changes.QueryChanges(&gerrit.QueryChangeOptions{
76			QueryOptions: gerrit.QueryOptions{Query: []string{query}},
77			Skip:         len(changes),
78		})
79		if err != nil {
80			if !g.authenticated {
81				err = fmt.Errorf(`query failed, possibly because of authentication.
82	See https://dawn-review.googlesource.com/new-password for obtaining a username
83	and password which can be provided with --gerrit-user and --gerrit-pass.
84	%w`, err)
85			}
86			return nil, "", err
87		}
88
89		changes = append(changes, *batch...)
90		if len(*batch) == 0 || !(*batch)[len(*batch)-1].MoreChanges {
91			break
92		}
93	}
94	return changes, query, nil
95}
96