@@ -2,13 +2,147 @@ package main
22
33import (
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+
12146func init () {
13147 usage := `
14148Examples:
@@ -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