File: http.go

package info (click to toggle)
gh 2.46.0-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,548 kB
  • sloc: sh: 227; makefile: 117
file content (135 lines) | stat: -rw-r--r-- 2,883 bytes parent folder | download | duplicates (3)
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
130
131
132
133
134
135
package label

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/cli/cli/v2/api"
	"github.com/cli/cli/v2/internal/ghrepo"
)

const (
	maxPageSize = 100

	defaultOrder = "asc"
	defaultSort  = "created"
)

var defaultFields = []string{
	"color",
	"description",
	"name",
}

type listLabelsResponseData struct {
	Repository struct {
		Labels struct {
			TotalCount int
			Nodes      []label
			PageInfo   struct {
				HasNextPage bool
				EndCursor   string
			}
		}
	}
}

type listQueryOptions struct {
	Limit int
	Query string
	Order string
	Sort  string

	fields []string
}

func (opts listQueryOptions) OrderBy() map[string]string {
	// Set on copy to keep original intact.
	if opts.Order == "" {
		opts.Order = defaultOrder
	}
	if opts.Sort == "" {
		opts.Sort = defaultSort
	}

	field := strings.ToUpper(opts.Sort)
	if opts.Sort == "created" {
		field = "CREATED_AT"
	}
	return map[string]string{
		"direction": strings.ToUpper(opts.Order),
		"field":     field,
	}
}

// listLabels lists the labels in the given repo. Pass -1 for limit to list all labels;
// otherwise, only that number of labels is returned for any number of pages.
func listLabels(client *http.Client, repo ghrepo.Interface, opts listQueryOptions) ([]label, int, error) {
	if len(opts.fields) == 0 {
		opts.fields = defaultFields
	}

	apiClient := api.NewClientFromHTTP(client)
	fragment := fmt.Sprintf("fragment label on Label{%s}", strings.Join(opts.fields, ","))
	query := fragment + `
	query LabelList($owner: String!, $repo: String!, $limit: Int!, $endCursor: String, $query: String, $orderBy: LabelOrder) {
		repository(owner: $owner, name: $repo) {
			labels(first: $limit, after: $endCursor, query: $query, orderBy: $orderBy) {
				totalCount,
				nodes {
					...label
				}
				pageInfo {
					hasNextPage
					endCursor
				}
			}
		}
	}`

	variables := map[string]interface{}{
		"owner":   repo.RepoOwner(),
		"repo":    repo.RepoName(),
		"orderBy": opts.OrderBy(),
		"query":   opts.Query,
	}

	var labels []label
	var totalCount int

loop:
	for {
		var response listLabelsResponseData
		variables["limit"] = determinePageSize(opts.Limit - len(labels))
		err := apiClient.GraphQL(repo.RepoHost(), query, variables, &response)
		if err != nil {
			return nil, 0, err
		}

		totalCount = response.Repository.Labels.TotalCount

		for _, label := range response.Repository.Labels.Nodes {
			labels = append(labels, label)
			if len(labels) == opts.Limit {
				break loop
			}
		}

		if response.Repository.Labels.PageInfo.HasNextPage {
			variables["endCursor"] = response.Repository.Labels.PageInfo.EndCursor
		} else {
			break
		}
	}

	return labels, totalCount, nil
}

func determinePageSize(numRequestedItems int) int {
	// If numRequestedItems is -1 then retrieve maxPageSize
	if numRequestedItems < 0 || numRequestedItems > maxPageSize {
		return maxPageSize
	}
	return numRequestedItems
}