Skip to content

Commit d63b5a9

Browse files
author
Nate Smith
authored
Merge pull request cli#1763 from Matt-Gleich/trunk
♻️ Refactor gist list to use graphQL
2 parents edec480 + cd2adfe commit d63b5a9

3 files changed

Lines changed: 313 additions & 128 deletions

File tree

pkg/cmd/gist/list/http.go

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,88 @@
11
package list
22

33
import (
4-
"fmt"
4+
"context"
55
"net/http"
6-
"net/url"
7-
"sort"
6+
"strings"
7+
"time"
88

9-
"github.com/cli/cli/api"
9+
"github.com/cli/cli/internal/ghinstance"
1010
"github.com/cli/cli/pkg/cmd/gist/shared"
11+
"github.com/shurcooL/githubv4"
12+
"github.com/shurcooL/graphql"
1113
)
1214

1315
func listGists(client *http.Client, hostname string, limit int, visibility string) ([]shared.Gist, error) {
14-
result := []shared.Gist{}
16+
type response struct {
17+
Viewer struct {
18+
Gists struct {
19+
Nodes []struct {
20+
Description string
21+
Files []struct {
22+
Name string
23+
}
24+
IsPublic bool
25+
Name string
26+
UpdatedAt time.Time
27+
}
28+
PageInfo struct {
29+
HasNextPage bool
30+
EndCursor string
31+
}
32+
} `graphql:"gists(first: $per_page, after: $endCursor, privacy: $visibility, orderBy: {field: CREATED_AT, direction: DESC})"`
33+
}
34+
}
1535

16-
query := url.Values{}
17-
if visibility == "all" {
18-
query.Add("per_page", fmt.Sprintf("%d", limit))
19-
} else {
20-
query.Add("per_page", "100")
36+
perPage := limit
37+
if perPage > 100 {
38+
perPage = 100
2139
}
2240

23-
// TODO switch to graphql
24-
apiClient := api.NewClientFromHTTP(client)
25-
err := apiClient.REST(hostname, "GET", "gists?"+query.Encode(), nil, &result)
26-
if err != nil {
27-
return nil, err
41+
variables := map[string]interface{}{
42+
"per_page": githubv4.Int(perPage),
43+
"endCursor": (*githubv4.String)(nil),
44+
"visibility": githubv4.GistPrivacy(strings.ToUpper(visibility)),
2845
}
2946

47+
gql := graphql.NewClient(ghinstance.GraphQLEndpoint(hostname), client)
48+
3049
gists := []shared.Gist{}
50+
pagination:
51+
for {
52+
var result response
53+
err := gql.QueryNamed(context.Background(), "GistList", &result, variables)
54+
if err != nil {
55+
return nil, err
56+
}
3157

32-
for _, gist := range result {
33-
if len(gists) == limit {
34-
break
58+
for _, gist := range result.Viewer.Gists.Nodes {
59+
files := map[string]*shared.GistFile{}
60+
for _, file := range gist.Files {
61+
files[file.Name] = &shared.GistFile{
62+
Filename: file.Name,
63+
}
64+
}
65+
66+
gists = append(
67+
gists,
68+
shared.Gist{
69+
ID: gist.Name,
70+
Description: gist.Description,
71+
Files: files,
72+
UpdatedAt: gist.UpdatedAt,
73+
Public: gist.IsPublic,
74+
},
75+
)
76+
if len(gists) == limit {
77+
break pagination
78+
}
3579
}
36-
if visibility == "all" || (visibility == "secret" && !gist.Public) || (visibility == "public" && gist.Public) {
37-
gists = append(gists, gist)
80+
81+
if !result.Viewer.Gists.PageInfo.HasNextPage {
82+
break
3883
}
84+
variables["endCursor"] = githubv4.String(result.Viewer.Gists.PageInfo.EndCursor)
3985
}
4086

41-
sort.SliceStable(gists, func(i, j int) bool {
42-
return gists[i].UpdatedAt.After(gists[j].UpdatedAt)
43-
})
44-
4587
return gists, nil
4688
}

pkg/cmd/gist/list/list.go

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/cli/cli/internal/ghinstance"
1010
"github.com/cli/cli/pkg/cmdutil"
1111
"github.com/cli/cli/pkg/iostreams"
12+
"github.com/cli/cli/pkg/text"
1213
"github.com/cli/cli/utils"
1314
"github.com/spf13/cobra"
1415
)
@@ -27,6 +28,9 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman
2728
HttpClient: f.HttpClient,
2829
}
2930

31+
var flagPublic bool
32+
var flagSecret bool
33+
3034
cmd := &cobra.Command{
3135
Use: "list",
3236
Short: "List your gists",
@@ -36,27 +40,23 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman
3640
return &cmdutil.FlagError{Err: fmt.Errorf("invalid limit: %v", opts.Limit)}
3741
}
3842

39-
pub := cmd.Flags().Changed("public")
40-
secret := cmd.Flags().Changed("secret")
41-
4243
opts.Visibility = "all"
43-
if pub && !secret {
44-
opts.Visibility = "public"
45-
} else if secret && !pub {
44+
if flagSecret {
4645
opts.Visibility = "secret"
46+
} else if flagPublic {
47+
opts.Visibility = "public"
4748
}
4849

4950
if runF != nil {
5051
return runF(opts)
5152
}
52-
5353
return listRun(opts)
5454
},
5555
}
5656

5757
cmd.Flags().IntVarP(&opts.Limit, "limit", "L", 10, "Maximum number of gists to fetch")
58-
cmd.Flags().Bool("public", false, "Show only public gists")
59-
cmd.Flags().Bool("secret", false, "Show only secret gists")
58+
cmd.Flags().BoolVar(&flagPublic, "public", false, "Show only public gists")
59+
cmd.Flags().BoolVar(&flagSecret, "secret", false, "Show only secret gists")
6060

6161
return cmd
6262
}
@@ -77,10 +77,7 @@ func listRun(opts *ListOptions) error {
7777
tp := utils.NewTablePrinter(opts.IO)
7878

7979
for _, gist := range gists {
80-
fileCount := 0
81-
for range gist.Files {
82-
fileCount++
83-
}
80+
fileCount := len(gist.Files)
8481

8582
visibility := "public"
8683
visColor := cs.Green
@@ -99,16 +96,16 @@ func listRun(opts *ListOptions) error {
9996
}
10097
}
10198

99+
gistTime := gist.UpdatedAt.Format(time.RFC3339)
100+
if tp.IsTTY() {
101+
gistTime = utils.FuzzyAgo(time.Since(gist.UpdatedAt))
102+
}
103+
102104
tp.AddField(gist.ID, nil, nil)
103-
tp.AddField(description, nil, cs.Bold)
105+
tp.AddField(text.ReplaceExcessiveWhitespace(description), nil, cs.Bold)
104106
tp.AddField(utils.Pluralize(fileCount, "file"), nil, nil)
105107
tp.AddField(visibility, nil, visColor)
106-
if tp.IsTTY() {
107-
updatedAt := utils.FuzzyAgo(time.Since(gist.UpdatedAt))
108-
tp.AddField(updatedAt, nil, cs.Gray)
109-
} else {
110-
tp.AddField(gist.UpdatedAt.String(), nil, nil)
111-
}
108+
tp.AddField(gistTime, nil, cs.Gray)
112109
tp.EndRow()
113110
}
114111

0 commit comments

Comments
 (0)