X Tutup
Skip to content

Commit 99574f8

Browse files
alexpjohnsonvilmibm
andauthored
Add a command to delete a gist (cli#2265)
* Add a command to delete a gist * minor cleanup Co-authored-by: vilmibm <vilmibm@github.com>
1 parent 116d581 commit 99574f8

File tree

3 files changed

+246
-0
lines changed

3 files changed

+246
-0
lines changed

pkg/cmd/gist/delete/delete.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package delete
2+
3+
import (
4+
"fmt"
5+
"github.com/cli/cli/api"
6+
"github.com/cli/cli/internal/ghinstance"
7+
"github.com/cli/cli/pkg/cmd/gist/shared"
8+
"github.com/cli/cli/pkg/cmdutil"
9+
"github.com/cli/cli/pkg/iostreams"
10+
"github.com/spf13/cobra"
11+
"net/http"
12+
"strings"
13+
)
14+
15+
type DeleteOptions struct {
16+
IO *iostreams.IOStreams
17+
HttpClient func() (*http.Client, error)
18+
19+
Selector string
20+
}
21+
22+
func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Command {
23+
opts := DeleteOptions{
24+
IO: f.IOStreams,
25+
HttpClient: f.HttpClient,
26+
}
27+
28+
cmd := &cobra.Command{
29+
Use: "delete {<gist ID> | <gist URL>}",
30+
Short: "Delete a gist",
31+
Args: cobra.ExactArgs(1),
32+
RunE: func(c *cobra.Command, args []string) error {
33+
opts.Selector = args[0]
34+
if runF != nil {
35+
return runF(&opts)
36+
}
37+
return deleteRun(&opts)
38+
},
39+
}
40+
return cmd
41+
}
42+
43+
func deleteRun(opts *DeleteOptions) error {
44+
gistID := opts.Selector
45+
46+
if strings.Contains(gistID, "/") {
47+
id, err := shared.GistIDFromURL(gistID)
48+
if err != nil {
49+
return err
50+
}
51+
gistID = id
52+
}
53+
client, err := opts.HttpClient()
54+
if err != nil {
55+
return err
56+
}
57+
58+
apiClient := api.NewClientFromHTTP(client)
59+
60+
gist, err := shared.GetGist(client, ghinstance.OverridableDefault(), gistID)
61+
if err != nil {
62+
return err
63+
}
64+
username, err := api.CurrentLoginName(apiClient, ghinstance.OverridableDefault())
65+
if err != nil {
66+
return err
67+
}
68+
69+
if username != gist.Owner.Login {
70+
return fmt.Errorf("You do not own this gist.")
71+
}
72+
73+
err = deleteGist(apiClient, ghinstance.OverridableDefault(), gistID)
74+
if err != nil {
75+
return err
76+
}
77+
78+
return nil
79+
}
80+
81+
func deleteGist(apiClient *api.Client, hostname string, gistID string) error {
82+
path := "gists/" + gistID
83+
err := apiClient.REST(hostname, "DELETE", path, nil, nil)
84+
if err != nil {
85+
return err
86+
}
87+
return nil
88+
}

pkg/cmd/gist/delete/delete_test.go

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package delete
2+
3+
import (
4+
"bytes"
5+
"github.com/cli/cli/pkg/cmd/gist/shared"
6+
"github.com/cli/cli/pkg/cmdutil"
7+
"github.com/cli/cli/pkg/httpmock"
8+
"github.com/cli/cli/pkg/iostreams"
9+
"github.com/cli/cli/pkg/prompt"
10+
"github.com/google/shlex"
11+
"github.com/stretchr/testify/assert"
12+
"net/http"
13+
"testing"
14+
)
15+
16+
func TestNewCmdDelete(t *testing.T) {
17+
tests := []struct {
18+
name string
19+
cli string
20+
wants DeleteOptions
21+
}{
22+
{
23+
name: "valid selector",
24+
cli: "123",
25+
wants: DeleteOptions{
26+
Selector: "123",
27+
},
28+
},
29+
}
30+
31+
for _, tt := range tests {
32+
t.Run(tt.name, func(t *testing.T) {
33+
f := &cmdutil.Factory{}
34+
35+
argv, err := shlex.Split(tt.cli)
36+
assert.NoError(t, err)
37+
var gotOpts *DeleteOptions
38+
cmd := NewCmdDelete(f, func(opts *DeleteOptions) error {
39+
gotOpts = opts
40+
return nil
41+
})
42+
43+
cmd.SetArgs(argv)
44+
cmd.SetIn(&bytes.Buffer{})
45+
cmd.SetOut(&bytes.Buffer{})
46+
cmd.SetErr(&bytes.Buffer{})
47+
48+
_, err = cmd.ExecuteC()
49+
assert.NoError(t, err)
50+
51+
assert.Equal(t, tt.wants.Selector, gotOpts.Selector)
52+
})
53+
}
54+
}
55+
56+
func Test_deleteRun(t *testing.T) {
57+
tests := []struct {
58+
name string
59+
opts *DeleteOptions
60+
gist *shared.Gist
61+
httpStubs func(*httpmock.Registry)
62+
askStubs func(*prompt.AskStubber)
63+
nontty bool
64+
wantErr bool
65+
wantStderr string
66+
wantParams map[string]interface{}
67+
}{
68+
{
69+
name: "no such gist",
70+
wantErr: true,
71+
}, {
72+
name: "another user's gist",
73+
gist: &shared.Gist{
74+
ID: "1234",
75+
Files: map[string]*shared.GistFile{
76+
"cicada.txt": {
77+
Filename: "cicada.txt",
78+
Content: "bwhiizzzbwhuiiizzzz",
79+
Type: "text/plain",
80+
},
81+
},
82+
Owner: &shared.GistOwner{Login: "octocat2"},
83+
},
84+
wantErr: true,
85+
wantStderr: "You do not own this gist.",
86+
}, {
87+
name: "successfully delete",
88+
gist: &shared.Gist{
89+
ID: "1234",
90+
Files: map[string]*shared.GistFile{
91+
"cicada.txt": {
92+
Filename: "cicada.txt",
93+
Content: "bwhiizzzbwhuiiizzzz",
94+
Type: "text/plain",
95+
},
96+
},
97+
Owner: &shared.GistOwner{Login: "octocat"},
98+
},
99+
httpStubs: func(reg *httpmock.Registry) {
100+
reg.Register(httpmock.REST("DELETE", "gists/1234"),
101+
httpmock.StatusStringResponse(200, "{}"))
102+
},
103+
wantErr: false,
104+
},
105+
}
106+
107+
for _, tt := range tests {
108+
reg := &httpmock.Registry{}
109+
if tt.gist == nil {
110+
reg.Register(httpmock.REST("GET", "gists/1234"),
111+
httpmock.StatusStringResponse(404, "Not Found"))
112+
} else {
113+
reg.Register(httpmock.REST("GET", "gists/1234"),
114+
httpmock.JSONResponse(tt.gist))
115+
reg.Register(httpmock.GraphQL(`query UserCurrent\b`),
116+
httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`))
117+
}
118+
119+
if tt.httpStubs != nil {
120+
tt.httpStubs(reg)
121+
}
122+
123+
as, teardown := prompt.InitAskStubber()
124+
defer teardown()
125+
if tt.askStubs != nil {
126+
tt.askStubs(as)
127+
}
128+
129+
if tt.opts == nil {
130+
tt.opts = &DeleteOptions{}
131+
}
132+
133+
tt.opts.HttpClient = func() (*http.Client, error) {
134+
return &http.Client{Transport: reg}, nil
135+
}
136+
io, _, _, _ := iostreams.Test()
137+
io.SetStdoutTTY(!tt.nontty)
138+
io.SetStdinTTY(!tt.nontty)
139+
tt.opts.IO = io
140+
tt.opts.Selector = "1234"
141+
142+
t.Run(tt.name, func(t *testing.T) {
143+
err := deleteRun(tt.opts)
144+
reg.Verify(t)
145+
if tt.wantErr {
146+
assert.Error(t, err)
147+
if tt.wantStderr != "" {
148+
assert.EqualError(t, err, tt.wantStderr)
149+
}
150+
return
151+
}
152+
assert.NoError(t, err)
153+
154+
})
155+
}
156+
}

pkg/cmd/gist/gist.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package gist
33
import (
44
"github.com/MakeNowJust/heredoc"
55
gistCreateCmd "github.com/cli/cli/pkg/cmd/gist/create"
6+
gistDeleteCmd "github.com/cli/cli/pkg/cmd/gist/delete"
67
gistEditCmd "github.com/cli/cli/pkg/cmd/gist/edit"
78
gistListCmd "github.com/cli/cli/pkg/cmd/gist/list"
89
gistViewCmd "github.com/cli/cli/pkg/cmd/gist/view"
@@ -29,6 +30,7 @@ func NewCmdGist(f *cmdutil.Factory) *cobra.Command {
2930
cmd.AddCommand(gistListCmd.NewCmdList(f, nil))
3031
cmd.AddCommand(gistViewCmd.NewCmdView(f, nil))
3132
cmd.AddCommand(gistEditCmd.NewCmdEdit(f, nil))
33+
cmd.AddCommand(gistDeleteCmd.NewCmdDelete(f, nil))
3234

3335
return cmd
3436
}

0 commit comments

Comments
 (0)
X Tutup