From baba8949973244a53f6a172a03afa84a7a0ccfc4 Mon Sep 17 00:00:00 2001 From: Kousik Mitra Date: Fri, 23 Jun 2023 17:38:21 +0530 Subject: [PATCH] Add option to remove file from gist (#7560) --- pkg/cmd/gist/edit/edit.go | 35 +++++++++++-- pkg/cmd/gist/edit/edit_test.go | 96 +++++++++++++++++++++++++++++++--- 2 files changed, 119 insertions(+), 12 deletions(-) diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index 3ad28b6c4..fffcc82ca 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -32,11 +32,12 @@ type EditOptions struct { Edit func(string, string, string, *iostreams.IOStreams) (string, error) - Selector string - EditFilename string - AddFilename string - SourceFile string - Description string + Selector string + EditFilename string + AddFilename string + RemoveFilename string + SourceFile string + Description string } func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Command { @@ -82,6 +83,10 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman cmd.Flags().StringVarP(&opts.AddFilename, "add", "a", "", "Add a new file to the gist") cmd.Flags().StringVarP(&opts.Description, "desc", "d", "", "New description for the gist") cmd.Flags().StringVarP(&opts.EditFilename, "filename", "f", "", "Select a file to edit") + cmd.Flags().StringVarP(&opts.RemoveFilename, "remove", "r", "", "Remove a file from the gist") + + cmd.MarkFlagsMutuallyExclusive("add", "remove") + cmd.MarkFlagsMutuallyExclusive("remove", "filename") return cmd } @@ -187,6 +192,16 @@ func editRun(opts *EditOptions) error { return updateGist(apiClient, host, gist) } + // Remove a file from the gist + if opts.RemoveFilename != "" { + err := removeFile(gist, opts.RemoveFilename) + if err != nil { + return err + } + + return updateGist(apiClient, host, gist) + } + filesToUpdate := map[string]string{} for { @@ -337,3 +352,13 @@ func getFilesToAdd(file string, content []byte) (map[string]*shared.GistFile, er }, }, nil } + +func removeFile(gist *shared.Gist, filename string) error { + if _, found := gist.Files[filename]; !found { + return fmt.Errorf("gist has no file %q", filename) + } + + gist.Files[filename] = nil + + return nil +} diff --git a/pkg/cmd/gist/edit/edit_test.go b/pkg/cmd/gist/edit/edit_test.go index 5e52a8ffb..481dd0a9c 100644 --- a/pkg/cmd/gist/edit/edit_test.go +++ b/pkg/cmd/gist/edit/edit_test.go @@ -36,9 +36,10 @@ func Test_getFilesToAdd(t *testing.T) { func TestNewCmdEdit(t *testing.T) { tests := []struct { - name string - cli string - wants EditOptions + name string + cli string + wants EditOptions + wantsErr bool }{ { name: "no flags", @@ -80,6 +81,24 @@ func TestNewCmdEdit(t *testing.T) { Description: "my new description", }, }, + { + name: "remove", + cli: "123 --remove cool.md", + wants: EditOptions{ + Selector: "123", + RemoveFilename: "cool.md", + }, + }, + { + name: "add and remove are mutually exclusive", + cli: "123 --add cool.md --remove great.md", + wantsErr: true, + }, + { + name: "filename and remove are mutually exclusive", + cli: "123 --filename cool.md --remove great.md", + wantsErr: true, + }, } for _, tt := range tests { @@ -100,11 +119,17 @@ func TestNewCmdEdit(t *testing.T) { cmd.SetErr(&bytes.Buffer{}) _, err = cmd.ExecuteC() - assert.NoError(t, err) + if tt.wantsErr { + require.Error(t, err) + return + } - assert.Equal(t, tt.wants.EditFilename, gotOpts.EditFilename) - assert.Equal(t, tt.wants.AddFilename, gotOpts.AddFilename) - assert.Equal(t, tt.wants.Selector, gotOpts.Selector) + require.NoError(t, err) + + require.Equal(t, tt.wants.EditFilename, gotOpts.EditFilename) + require.Equal(t, tt.wants.AddFilename, gotOpts.AddFilename) + require.Equal(t, tt.wants.Selector, gotOpts.Selector) + require.Equal(t, tt.wants.RemoveFilename, gotOpts.RemoveFilename) }) } } @@ -394,6 +419,63 @@ func Test_editRun(t *testing.T) { }, }, }, + { + name: "remove file, file does not exist", + gist: &shared.Gist{ + ID: "1234", + Files: map[string]*shared.GistFile{ + "sample.txt": { + Filename: "sample.txt", + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + }, + Owner: &shared.GistOwner{Login: "octocat"}, + }, + opts: &EditOptions{ + RemoveFilename: "sample2.txt", + }, + wantErr: "gist has no file \"sample2.txt\"", + }, + { + name: "remove file from existing gist", + gist: &shared.Gist{ + ID: "1234", + Files: map[string]*shared.GistFile{ + "sample.txt": { + Filename: "sample.txt", + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + "sample2.txt": { + Filename: "sample2.txt", + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + }, + Owner: &shared.GistOwner{Login: "octocat"}, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("POST", "gists/1234"), + httpmock.StatusStringResponse(201, "{}")) + }, + opts: &EditOptions{ + RemoveFilename: "sample2.txt", + }, + wantParams: map[string]interface{}{ + "description": "", + "updated_at": "0001-01-01T00:00:00Z", + "public": false, + "files": map[string]interface{}{ + "sample.txt": map[string]interface{}{ + "filename": "sample.txt", + "content": "bwhiizzzbwhuiiizzzz", + "type": "text/plain", + }, + "sample2.txt": nil, + }, + }, + }, { name: "edit gist using file from source parameter", gist: &shared.Gist{