Skip to content

Commit 25f8c02

Browse files
committed
update src repo list to skip repos that have errors
1 parent 9fcfd4c commit 25f8c02

File tree

1 file changed

+157
-45
lines changed

1 file changed

+157
-45
lines changed

cmd/src/repos_list.go

Lines changed: 157 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,147 @@ package main
22

33
import (
44
"context"
5+
"encoding/json"
56
"flag"
67
"fmt"
78
"strings"
89

910
"github.com/sourcegraph/src-cli/internal/api"
1011
)
1112

13+
type reposListOptions struct {
14+
first int
15+
query string
16+
cloned bool
17+
notCloned bool
18+
indexed bool
19+
notIndexed bool
20+
orderBy string
21+
descending bool
22+
}
23+
24+
type repositoriesListResult struct {
25+
Data struct {
26+
Repositories struct {
27+
Nodes []Repository `json:"nodes"`
28+
} `json:"repositories"`
29+
} `json:"data"`
30+
Errors []json.RawMessage `json:"errors,omitempty"`
31+
}
32+
33+
func listRepositories(ctx context.Context, client api.Client, params reposListOptions) ([]Repository, []Repository, error) {
34+
query := `query Repositories(
35+
$first: Int,
36+
$query: String,
37+
$cloned: Boolean,
38+
$notCloned: Boolean,
39+
$indexed: Boolean,
40+
$notIndexed: Boolean,
41+
$orderBy: RepositoryOrderBy,
42+
$descending: Boolean,
43+
) {
44+
repositories(
45+
first: $first,
46+
query: $query,
47+
cloned: $cloned,
48+
notCloned: $notCloned,
49+
indexed: $indexed,
50+
notIndexed: $notIndexed,
51+
orderBy: $orderBy,
52+
descending: $descending,
53+
) {
54+
nodes {
55+
...RepositoryFields
56+
}
57+
}
58+
}
59+
` + repositoryFragment
60+
61+
var result repositoriesListResult
62+
ok, err := client.NewRequest(query, map[string]any{
63+
"first": api.NullInt(params.first),
64+
"query": api.NullString(params.query),
65+
"cloned": params.cloned,
66+
"notCloned": params.notCloned,
67+
"indexed": params.indexed,
68+
"notIndexed": params.notIndexed,
69+
"orderBy": params.orderBy,
70+
"descending": params.descending,
71+
}).DoRaw(ctx, &result)
72+
if err != nil || !ok {
73+
return nil, nil, err
74+
}
75+
if len(result.Errors) == 0 {
76+
return result.Data.Repositories.Nodes, nil, nil
77+
}
78+
79+
errors := api.NewGraphQlErrors(result.Errors)
80+
repos, skipped, ok := filterRepositoriesWithErrors(result.Data.Repositories.Nodes, errors)
81+
if ok {
82+
return repos, skipped, nil
83+
}
84+
85+
return nil, nil, errors
86+
}
87+
88+
func filterRepositoriesWithErrors(repos []Repository, errors api.GraphQlErrors) ([]Repository, []Repository, bool) {
89+
if len(errors) == 0 {
90+
return repos, nil, true
91+
}
92+
93+
skip := make(map[int]struct{}, len(errors))
94+
for _, graphQLError := range errors {
95+
path, err := graphQLError.Path()
96+
if err != nil || len(path) < 3 {
97+
return nil, nil, false
98+
}
99+
100+
pathRoot, ok := gqlErrorPathString(path[0])
101+
if !ok || pathRoot != "repositories" {
102+
return nil, nil, false
103+
}
104+
pathCollection, ok := gqlErrorPathString(path[1])
105+
if !ok || pathCollection != "nodes" {
106+
return nil, nil, false
107+
}
108+
109+
index, ok := gqlErrorIndex(path[2])
110+
if !ok {
111+
return nil, nil, false
112+
}
113+
skip[index] = struct{}{}
114+
}
115+
116+
filtered := make([]Repository, 0, len(repos))
117+
skipped := []Repository{}
118+
for i, repo := range repos {
119+
if _, ok := skip[i]; ok {
120+
skipped = append(skipped, repo)
121+
continue
122+
}
123+
filtered = append(filtered, repo)
124+
}
125+
126+
return filtered, skipped, true
127+
}
128+
129+
func gqlErrorPathString(pathSegment any) (string, bool) {
130+
value, ok := pathSegment.(string)
131+
return value, ok
132+
}
133+
134+
func gqlErrorIndex(pathSegment any) (int, bool) {
135+
switch value := pathSegment.(type) {
136+
case float64:
137+
index := int(value)
138+
return index, float64(index) == value && index >= 0
139+
case int:
140+
return value, value >= 0
141+
default:
142+
return 0, false
143+
}
144+
}
145+
12146
func init() {
13147
usage := `
14148
Examples:
@@ -64,33 +198,6 @@ Examples:
64198
return err
65199
}
66200

67-
query := `query Repositories(
68-
$first: Int,
69-
$query: String,
70-
$cloned: Boolean,
71-
$notCloned: Boolean,
72-
$indexed: Boolean,
73-
$notIndexed: Boolean,
74-
$orderBy: RepositoryOrderBy,
75-
$descending: Boolean,
76-
) {
77-
repositories(
78-
first: $first,
79-
query: $query,
80-
cloned: $cloned,
81-
notCloned: $notCloned,
82-
indexed: $indexed,
83-
notIndexed: $notIndexed,
84-
orderBy: $orderBy,
85-
descending: $descending,
86-
) {
87-
nodes {
88-
...RepositoryFields
89-
}
90-
}
91-
}
92-
` + repositoryFragment
93-
94201
var orderBy string
95202
switch *orderByFlag {
96203
case "name":
@@ -101,35 +208,40 @@ Examples:
101208
return fmt.Errorf("invalid -order-by flag value: %q", *orderByFlag)
102209
}
103210

104-
var result struct {
105-
Repositories struct {
106-
Nodes []Repository
107-
}
108-
}
109-
if ok, err := client.NewRequest(query, map[string]any{
110-
"first": api.NullInt(*firstFlag),
111-
"query": api.NullString(*queryFlag),
112-
"cloned": *clonedFlag,
113-
"notCloned": *notClonedFlag,
114-
"indexed": *indexedFlag,
115-
"notIndexed": *notIndexedFlag,
116-
"orderBy": orderBy,
117-
"descending": *descendingFlag,
118-
}).Do(context.Background(), &result); err != nil || !ok {
211+
repos, skipped, err := listRepositories(context.Background(), client, reposListOptions{
212+
first: *firstFlag,
213+
query: *queryFlag,
214+
cloned: *clonedFlag,
215+
notCloned: *notClonedFlag,
216+
indexed: *indexedFlag,
217+
notIndexed: *notIndexedFlag,
218+
orderBy: orderBy,
219+
descending: *descendingFlag,
220+
})
221+
if err != nil {
119222
return err
120223
}
121224

122-
for _, repo := range result.Repositories.Nodes {
225+
fmtRepo := func(repo Repository) string {
226+
firstSlash := strings.Index(repo.Name, "/")
227+
return repo.Name[firstSlash+len("/"):]
228+
}
229+
for _, repo := range repos {
123230
if *namesWithoutHostFlag {
124-
firstSlash := strings.Index(repo.Name, "/")
125-
fmt.Println(repo.Name[firstSlash+len("/"):])
231+
fmtRepo(repo)
126232
continue
127233
}
128234

129235
if err := execTemplate(tmpl, repo); err != nil {
130236
return err
131237
}
132238
}
239+
if len(skipped) > 0 {
240+
fmt.Printf("warning: skipped %d repos due to errors during listing\n", len(skipped))
241+
for _, skip := range skipped {
242+
fmt.Printf(" %s\n", fmtRepo(skip))
243+
}
244+
}
133245
return nil
134246
}
135247

0 commit comments

Comments
 (0)