gh gist list

This commit is contained in:
vilmibm 2020-09-10 20:14:29 -05:00
parent b34fe8123a
commit f7c4a0cf3f
4 changed files with 228 additions and 0 deletions

View file

@ -2,6 +2,7 @@ package gist
import (
gistCreateCmd "github.com/cli/cli/pkg/cmd/gist/create"
gistListCmd "github.com/cli/cli/pkg/cmd/gist/list"
"github.com/cli/cli/pkg/cmdutil"
"github.com/spf13/cobra"
)
@ -14,6 +15,7 @@ func NewCmdGist(f *cmdutil.Factory) *cobra.Command {
}
cmd.AddCommand(gistCreateCmd.NewCmdCreate(f, nil))
cmd.AddCommand(gistListCmd.NewCmdList(f, nil))
return cmd
}

52
pkg/cmd/gist/list/http.go Normal file
View file

@ -0,0 +1,52 @@
package list
import (
"fmt"
"net/http"
"net/url"
"sort"
"time"
"github.com/cli/cli/api"
)
type Gist struct {
Description string `json:"description"`
HTMLURL string `json:"html_url"`
UpdatedAt time.Time `json:"updated_at"`
Public bool
}
func listGists(client *http.Client, hostname string, limit int, visibility string) ([]Gist, error) {
result := []Gist{}
query := url.Values{}
if visibility == "all" {
query.Add("per_page", fmt.Sprintf("%d", limit))
} else {
query.Add("per_page", "100")
}
apiClient := api.NewClientFromHTTP(client)
err := apiClient.REST(hostname, "GET", "gists?"+query.Encode(), nil, &result)
if err != nil {
return nil, err
}
gists := []Gist{}
for _, gist := range result {
if len(gists) == limit {
break
}
if visibility == "all" || (visibility == "private" && !gist.Public) || (visibility == "public" && gist.Public) {
gists = append(gists, gist)
}
}
sort.SliceStable(gists, func(i, j int) bool {
return gists[i].UpdatedAt.After(gists[j].UpdatedAt)
})
return gists, nil
}

90
pkg/cmd/gist/list/list.go Normal file
View file

@ -0,0 +1,90 @@
package list
import (
"fmt"
"net/http"
"github.com/cli/cli/internal/ghinstance"
"github.com/cli/cli/pkg/cmdutil"
"github.com/cli/cli/pkg/iostreams"
"github.com/cli/cli/utils"
"github.com/spf13/cobra"
)
type ListOptions struct {
IO *iostreams.IOStreams
HttpClient func() (*http.Client, error)
Limit int
Visibility string // all, secret, public
}
func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command {
opts := &ListOptions{
IO: f.IOStreams,
HttpClient: f.HttpClient,
}
cmd := &cobra.Command{
Use: "list",
Short: "List your gists",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
if opts.Limit < 1 {
return &cmdutil.FlagError{Err: fmt.Errorf("invalid limit: %v", opts.Limit)}
}
pub := cmd.Flags().Changed("public")
priv := cmd.Flags().Changed("private")
opts.Visibility = "all"
if pub && !priv {
opts.Visibility = "public"
} else if priv && !pub {
opts.Visibility = "private"
}
if runF != nil {
return runF(opts)
}
return listRun(opts)
},
}
cmd.Flags().IntVarP(&opts.Limit, "limit", "L", 10, "Maximum number of gists to fetch")
cmd.Flags().Bool("public", false, "Show only public gists")
cmd.Flags().Bool("private", false, "Show only private gists")
return cmd
}
func listRun(opts *ListOptions) error {
client, err := opts.HttpClient()
if err != nil {
return err
}
gists, err := listGists(client, ghinstance.OverridableDefault(), opts.Limit, opts.Visibility)
if err != nil {
return err
}
cs := opts.IO.ColorScheme()
tp := utils.NewTablePrinter(opts.IO)
for _, gist := range gists {
// TODO i was getting confusing results with table printer's truncation
description := gist.Description
if len(description) > 40 {
description = description[0:37] + "..."
}
tp.AddField(description, nil, cs.Bold)
tp.AddField(gist.HTMLURL, nil, nil)
tp.EndRow()
}
return tp.Render()
}

View file

@ -0,0 +1,84 @@
package list
import (
"bytes"
"testing"
"github.com/cli/cli/pkg/cmdutil"
"github.com/google/shlex"
"github.com/stretchr/testify/assert"
)
func TestNewCmdList(t *testing.T) {
tests := []struct {
name string
cli string
wants ListOptions
}{
{
name: "no arguments",
cli: "",
wants: ListOptions{
Limit: 10,
Visibility: "all",
},
},
{
name: "public",
cli: "--public",
wants: ListOptions{
Limit: 10,
Visibility: "public",
},
},
{
name: "private",
cli: "--private",
wants: ListOptions{
Limit: 10,
Visibility: "private",
},
},
{
name: "public and private",
cli: "--private --public",
wants: ListOptions{
Limit: 10,
Visibility: "all",
},
},
{
name: "limit",
cli: "--limit 30",
wants: ListOptions{
Limit: 30,
Visibility: "all",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := &cmdutil.Factory{}
argv, err := shlex.Split(tt.cli)
assert.NoError(t, err)
var gotOpts *ListOptions
cmd := NewCmdList(f, func(opts *ListOptions) error {
gotOpts = opts
return nil
})
cmd.SetArgs(argv)
cmd.SetIn(&bytes.Buffer{})
cmd.SetOut(&bytes.Buffer{})
cmd.SetErr(&bytes.Buffer{})
_, err = cmd.ExecuteC()
assert.NoError(t, err)
assert.Equal(t, tt.wants.Visibility, gotOpts.Visibility)
assert.Equal(t, tt.wants.Limit, gotOpts.Limit)
})
}
}