Skip to content

Commit 9a149d7

Browse files
committed
Add repo list command
1 parent 962791b commit 9a149d7

File tree

3 files changed

+402
-0
lines changed

3 files changed

+402
-0
lines changed

pkg/cmd/repo/list/http.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package list
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/cli/cli/api"
8+
"github.com/shurcooL/githubv4"
9+
)
10+
11+
type RepositoryList struct {
12+
Repositories []Repository
13+
TotalCount int
14+
}
15+
16+
func listRepos(client *api.Client, hostname string, limit int, owner string, filter FilterOptions) (*RepositoryList, error) {
17+
type reposBlock struct {
18+
TotalCount int
19+
RepositoryCount int
20+
Nodes []Repository
21+
PageInfo struct {
22+
HasNextPage bool
23+
EndCursor string
24+
}
25+
}
26+
27+
type response struct {
28+
RepositoryOwner struct {
29+
Repositories reposBlock
30+
}
31+
Search reposBlock
32+
}
33+
34+
fragment := `
35+
fragment repo on Repository {
36+
nameWithOwner
37+
description
38+
isFork
39+
isPrivate
40+
isArchived
41+
updatedAt
42+
}`
43+
44+
// If `--archived` wasn't specified, use `repositoryOwner.repositores`
45+
query := fragment + `
46+
query RepoList($owner: String!, $per_page: Int!, $endCursor: String, $fork: Boolean, $privacy: RepositoryPrivacy) {
47+
repositoryOwner(login: $owner) {
48+
repositories(
49+
first: $per_page,
50+
after: $endCursor,
51+
privacy: $privacy,
52+
isFork: $fork,
53+
ownerAffiliations: OWNER,
54+
orderBy: { field: UPDATED_AT, direction: DESC }) {
55+
totalCount
56+
nodes {
57+
...repo
58+
}
59+
pageInfo {
60+
hasNextPage
61+
endCursor
62+
}
63+
}
64+
}
65+
}`
66+
67+
perPage := limit
68+
if perPage > 100 {
69+
perPage = 100
70+
}
71+
72+
variables := map[string]interface{}{
73+
"per_page": githubv4.Int(perPage),
74+
"endCursor": (*githubv4.String)(nil),
75+
}
76+
77+
hasArchivedFilter := filter.Archived
78+
79+
if hasArchivedFilter {
80+
// If `--archived` was specified, use the `search` API rather than
81+
// `repositoryOwner.repositories`
82+
query = fragment + `
83+
query RepoList($per_page: Int!, $endCursor: String, $query: String!) {
84+
search(first: $per_page, after:$endCursor, type: REPOSITORY, query: $query) {
85+
repositoryCount
86+
nodes {
87+
... on Repository {
88+
...repo
89+
}
90+
}
91+
pageInfo {
92+
hasNextPage
93+
endCursor
94+
}
95+
}
96+
}`
97+
98+
search := []string{fmt.Sprintf("user:%s archived:true fork:true sort:updated-desc", owner)}
99+
100+
switch filter.Visibility {
101+
case "private":
102+
search = append(search, "is:private")
103+
case "public":
104+
search = append(search, "is:public")
105+
default:
106+
search = append(search, "is:all")
107+
}
108+
109+
variables["query"] = strings.Join(search, " ")
110+
} else {
111+
variables["owner"] = githubv4.String(owner)
112+
113+
if filter.Visibility != "" {
114+
variables["privacy"] = githubv4.RepositoryPrivacy(strings.ToUpper(filter.Visibility))
115+
} else {
116+
variables["privacy"] = (*githubv4.RepositoryPrivacy)(nil)
117+
}
118+
119+
if filter.Fork {
120+
variables["fork"] = githubv4.Boolean(true)
121+
} else if filter.Source {
122+
variables["fork"] = githubv4.Boolean(false)
123+
} else {
124+
variables["fork"] = (*githubv4.Boolean)(nil)
125+
}
126+
}
127+
128+
var repos []Repository
129+
var totalCount int
130+
131+
var result response
132+
133+
pagination:
134+
for {
135+
err := client.GraphQL(hostname, query, variables, &result)
136+
if err != nil {
137+
return nil, err
138+
}
139+
140+
if hasArchivedFilter {
141+
repos = append(repos, result.Search.Nodes...)
142+
} else {
143+
repos = append(repos, result.RepositoryOwner.Repositories.Nodes...)
144+
}
145+
146+
if len(repos) >= limit {
147+
if len(repos) > limit {
148+
repos = repos[:limit]
149+
}
150+
break pagination
151+
}
152+
153+
if !result.RepositoryOwner.Repositories.PageInfo.HasNextPage {
154+
if !result.Search.PageInfo.HasNextPage {
155+
break
156+
}
157+
}
158+
159+
variables["endCursor"] = githubv4.String(result.RepositoryOwner.Repositories.PageInfo.EndCursor)
160+
if hasArchivedFilter {
161+
variables["endCursor"] = githubv4.String(result.Search.PageInfo.EndCursor)
162+
}
163+
}
164+
165+
totalCount = result.RepositoryOwner.Repositories.TotalCount
166+
if hasArchivedFilter {
167+
totalCount = result.Search.RepositoryCount
168+
}
169+
170+
listResult := &RepositoryList{
171+
Repositories: repos,
172+
TotalCount: totalCount,
173+
}
174+
175+
return listResult, nil
176+
}

0 commit comments

Comments
 (0)