From 025f86b9113430e3c7e86de00a2f09e9b8acc54f Mon Sep 17 00:00:00 2001 From: meiji163 Date: Wed, 6 Oct 2021 12:49:06 -0700 Subject: [PATCH 1/7] init commit --- pkg/cmd/repo/delete/delete.go | 48 +++++++++++++++++++++++++++++++++++ pkg/cmd/repo/delete/http.go | 9 +++++++ 2 files changed, 57 insertions(+) create mode 100644 pkg/cmd/repo/delete/delete.go create mode 100644 pkg/cmd/repo/delete/http.go diff --git a/pkg/cmd/repo/delete/delete.go b/pkg/cmd/repo/delete/delete.go new file mode 100644 index 000000000..8af75b203 --- /dev/null +++ b/pkg/cmd/repo/delete/delete.go @@ -0,0 +1,48 @@ +package delete + +import ( + "net/http" + + "github.com/cli/cli/v2/pkg/cmdutil" + + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/spf13/cobra" +) + +type DeleteOptions struct { + HttpClient func() (*http.Client, error) + IO *iostreams.IOStreams + RepoArg string + Confirmed bool +} + +func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Command { + opts := &DeleteOptions{ + IO: f.IOStreams, + HttpClient: f.HttpClient, + } + + cmd := &cobra.Command{ + Use: "delete ", + Short: "Delete a repository", + Long: `Delete a GitHub repository. + + Ensure that you have authorized the \"delete_repo\" scope: gh auth refresh -h github.com -s delete_repo"`, + Args: cmdutil.ExactArgs(1, "cannot delete: repository argument required"), + RunE: func(cmd *cobra.Command, args []string) error { + opts.RepoArg = args[0] + if runF != nil { + return runF(opts) + } + return deleteRun(opts) + }, + } + + cmd.Flags().BoolVar(&opts.Confirmed, "yes", false, "Confirm deletion without prompting") + return cmd +} + +func deleteRun(opts *DeleteOptions) error { + + return nil +} diff --git a/pkg/cmd/repo/delete/http.go b/pkg/cmd/repo/delete/http.go new file mode 100644 index 000000000..4e04b5c52 --- /dev/null +++ b/pkg/cmd/repo/delete/http.go @@ -0,0 +1,9 @@ +package delete + +import ( + "net/http" +) + +func deleteRepo(client *http.Client) error { + +} From a8028be8f9f19972175b3c2219c40dfd122a5cd6 Mon Sep 17 00:00:00 2001 From: meiji163 Date: Thu, 7 Oct 2021 09:53:22 -0700 Subject: [PATCH 2/7] add delete HTTP request and confirmation prompting --- pkg/cmd/repo/delete/delete.go | 70 ++++++++++++++++++++++++++++++++++- pkg/cmd/repo/delete/http.go | 32 +++++++++++++++- pkg/cmd/repo/repo.go | 2 + 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/repo/delete/delete.go b/pkg/cmd/repo/delete/delete.go index 8af75b203..04803c7a1 100644 --- a/pkg/cmd/repo/delete/delete.go +++ b/pkg/cmd/repo/delete/delete.go @@ -1,10 +1,18 @@ package delete import ( + "errors" + "fmt" "net/http" + "strings" + "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/internal/ghinstance" + "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/prompt" + "github.com/AlecAivazis/survey/v2" "github.com/cli/cli/v2/pkg/iostreams" "github.com/spf13/cobra" ) @@ -27,7 +35,8 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co Short: "Delete a repository", Long: `Delete a GitHub repository. - Ensure that you have authorized the \"delete_repo\" scope: gh auth refresh -h github.com -s delete_repo"`, +Deletion requires authorization with the "delete_repo" scope. +To authorize, run "gh auth refresh -h github.com -s delete_repo"`, Args: cmdutil.ExactArgs(1, "cannot delete: repository argument required"), RunE: func(cmd *cobra.Command, args []string) error { opts.RepoArg = args[0] @@ -38,11 +47,68 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co }, } - cmd.Flags().BoolVar(&opts.Confirmed, "yes", false, "Confirm deletion without prompting") + cmd.Flags().BoolVar(&opts.Confirmed, "yes", false, "confirm deletion without prompting") return cmd } func deleteRun(opts *DeleteOptions) error { + httpClient, err := opts.HttpClient() + if err != nil { + return err + } + apiClient := api.NewClientFromHTTP(httpClient) + + deleteURL := opts.RepoArg + var toDelete ghrepo.Interface + + if !strings.Contains(deleteURL, "/") { + currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) + if err != nil { + return err + } + deleteURL = currentUser + "/" + deleteURL + } + toDelete, err = ghrepo.FromFullName(deleteURL) + if err != nil { + return fmt.Errorf("argument error: %w", err) + } + + fullName := ghrepo.FullName(toDelete) + + doPrompt := opts.IO.CanPrompt() + if !opts.Confirmed && !doPrompt { + return errors.New("could not prompt: confirmation with prompt or --yes flag required") + } + + if !opts.Confirmed && doPrompt { + var valid string + err := prompt.SurveyAskOne( + &survey.Input{Message: fmt.Sprintf("Type %s to confirm deletion:", fullName)}, + &valid, + survey.WithValidator( + func(val interface{}) error { + if str := val.(string); str != fullName { + return fmt.Errorf("You entered %s", str) + } + return nil + })) + if err != nil { + return fmt.Errorf("could not prompt: %w", err) + } + } + + err = deleteRepo(httpClient, toDelete) + if err != nil { + return fmt.Errorf("API call failed: %w", err) + } + + if opts.IO.IsStdoutTTY() { + cs := opts.IO.ColorScheme() + fmt.Fprintf(opts.IO.Out, + "%s Deleted repository %s\n", + cs.SuccessIcon(), + fullName) + } return nil } diff --git a/pkg/cmd/repo/delete/http.go b/pkg/cmd/repo/delete/http.go index 4e04b5c52..2875c54bc 100644 --- a/pkg/cmd/repo/delete/http.go +++ b/pkg/cmd/repo/delete/http.go @@ -1,9 +1,39 @@ package delete import ( + "fmt" "net/http" + + "github.com/cli/cli/v2/api" + "github.com/cli/cli/v2/internal/ghinstance" + "github.com/cli/cli/v2/internal/ghrepo" ) -func deleteRepo(client *http.Client) error { +func deleteRepo(client *http.Client, repo ghrepo.Interface) error { + url := fmt.Sprintf("%srepos/%s", + ghinstance.RESTPrefix(repo.RepoHost()), + ghrepo.FullName(repo)) + request, err := http.NewRequest("DELETE", url, nil) + request.Header.Set("Accept", "application/vnd.github.v3+json") + if err != nil { + return err + } + + resp, err := client.Do(request) + if err != nil { + return err + } + defer resp.Body.Close() + + err = api.HandleHTTPError(resp) + if resp.StatusCode == 403 { + return fmt.Errorf(`%w + +Deletion requires authorization with the "delete_repo" scope. To authorize, run "gh auth refresh -s delete_repo"`, err) + } else if resp.StatusCode > 204 { + return err + } + + return nil } diff --git a/pkg/cmd/repo/repo.go b/pkg/cmd/repo/repo.go index 252c322e9..a061f186c 100644 --- a/pkg/cmd/repo/repo.go +++ b/pkg/cmd/repo/repo.go @@ -5,6 +5,7 @@ import ( repoCloneCmd "github.com/cli/cli/v2/pkg/cmd/repo/clone" repoCreateCmd "github.com/cli/cli/v2/pkg/cmd/repo/create" creditsCmd "github.com/cli/cli/v2/pkg/cmd/repo/credits" + repoDeleteCmd "github.com/cli/cli/v2/pkg/cmd/repo/delete" repoForkCmd "github.com/cli/cli/v2/pkg/cmd/repo/fork" gardenCmd "github.com/cli/cli/v2/pkg/cmd/repo/garden" repoListCmd "github.com/cli/cli/v2/pkg/cmd/repo/list" @@ -42,6 +43,7 @@ func NewCmdRepo(f *cmdutil.Factory) *cobra.Command { cmd.AddCommand(repoSyncCmd.NewCmdSync(f, nil)) cmd.AddCommand(creditsCmd.NewCmdRepoCredits(f, nil)) cmd.AddCommand(gardenCmd.NewCmdGarden(f, nil)) + cmd.AddCommand(repoDeleteCmd.NewCmdDelete(f, nil)) return cmd } From 9ea36de269f593e5104266a690f9a62471a26125 Mon Sep 17 00:00:00 2001 From: meiji163 Date: Fri, 8 Oct 2021 20:32:07 -0700 Subject: [PATCH 3/7] add tests --- pkg/cmd/repo/delete/delete_test.go | 89 ++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 pkg/cmd/repo/delete/delete_test.go diff --git a/pkg/cmd/repo/delete/delete_test.go b/pkg/cmd/repo/delete/delete_test.go new file mode 100644 index 000000000..963b85c98 --- /dev/null +++ b/pkg/cmd/repo/delete/delete_test.go @@ -0,0 +1,89 @@ +package delete + +import ( + "net/http" + "testing" + + "github.com/cli/cli/v2/pkg/httpmock" + "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/prompt" + "github.com/stretchr/testify/assert" +) + +func Test_deleteRun(t *testing.T) { + tests := []struct { + name string + tty bool + opts *DeleteOptions + httpStubs func(*httpmock.Registry) + askStubs func(*prompt.AskStubber) + wantStdout string + wantErr bool + errMsg string + }{ + { + name: "prompting confirmation tty", + tty: true, + opts: &DeleteOptions{RepoArg: "OWNER/REPO"}, + wantStdout: "✓ Deleted repository OWNER/REPO\n", + askStubs: func(q *prompt.AskStubber) { + q.StubOne("NOTOWNER/NOTREPO") // this always passes?? + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("DELETE", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + }, + { + name: "confimation no tty", + opts: &DeleteOptions{ + RepoArg: "OWNER/REPO", + Confirmed: true, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("DELETE", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + }, + { + name: "no confirmation no tty", + opts: &DeleteOptions{RepoArg: "OWNER/REPO"}, + wantErr: true, + errMsg: "could not prompt: confirmation with prompt or --yes flag required", + }, + } + for _, tt := range tests { + q, teardown := prompt.InitAskStubber() + defer teardown() + if tt.askStubs != nil { + tt.askStubs(q) + } + + reg := &httpmock.Registry{} + if tt.httpStubs != nil { + tt.httpStubs(reg) + } + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: reg}, nil + } + + io, _, stdout, _ := iostreams.Test() + io.SetStdinTTY(tt.tty) + io.SetStdoutTTY(tt.tty) + tt.opts.IO = io + + t.Run(tt.name, func(t *testing.T) { + defer reg.Verify(t) + err := deleteRun(tt.opts) + if tt.wantErr { + assert.Error(t, err) + assert.Equal(t, tt.errMsg, err.Error()) + return + } + assert.NoError(t, err) + assert.Equal(t, tt.wantStdout, stdout.String()) + }) + } +} From 5d433021bde4ac946957df78d44bd41d102e9d4e Mon Sep 17 00:00:00 2001 From: meiji163 Date: Tue, 12 Oct 2021 10:16:14 -0700 Subject: [PATCH 4/7] simplify err handling and change flags --- pkg/cmd/repo/delete/delete.go | 6 +++--- pkg/cmd/repo/delete/delete_test.go | 6 ++++-- pkg/cmd/repo/delete/http.go | 10 ++-------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/pkg/cmd/repo/delete/delete.go b/pkg/cmd/repo/delete/delete.go index 04803c7a1..de7debd64 100644 --- a/pkg/cmd/repo/delete/delete.go +++ b/pkg/cmd/repo/delete/delete.go @@ -36,7 +36,7 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co Long: `Delete a GitHub repository. Deletion requires authorization with the "delete_repo" scope. -To authorize, run "gh auth refresh -h github.com -s delete_repo"`, +To authorize, run "gh auth refresh -s delete_repo"`, Args: cmdutil.ExactArgs(1, "cannot delete: repository argument required"), RunE: func(cmd *cobra.Command, args []string) error { opts.RepoArg = args[0] @@ -47,7 +47,7 @@ To authorize, run "gh auth refresh -h github.com -s delete_repo"`, }, } - cmd.Flags().BoolVar(&opts.Confirmed, "yes", false, "confirm deletion without prompting") + cmd.Flags().BoolVarP(&opts.Confirmed, "confirm", "c", false, "confirm deletion without prompting") return cmd } @@ -77,7 +77,7 @@ func deleteRun(opts *DeleteOptions) error { doPrompt := opts.IO.CanPrompt() if !opts.Confirmed && !doPrompt { - return errors.New("could not prompt: confirmation with prompt or --yes flag required") + return errors.New("could not prompt: confirmation with prompt or --confirm flag required") } if !opts.Confirmed && doPrompt { diff --git a/pkg/cmd/repo/delete/delete_test.go b/pkg/cmd/repo/delete/delete_test.go index 963b85c98..87ec0ed91 100644 --- a/pkg/cmd/repo/delete/delete_test.go +++ b/pkg/cmd/repo/delete/delete_test.go @@ -27,7 +27,9 @@ func Test_deleteRun(t *testing.T) { opts: &DeleteOptions{RepoArg: "OWNER/REPO"}, wantStdout: "✓ Deleted repository OWNER/REPO\n", askStubs: func(q *prompt.AskStubber) { - q.StubOne("NOTOWNER/NOTREPO") // this always passes?? + // TODO: survey stubber doesn't have WithValidation support + // so this always passes regardless of prompt input + q.StubOne("OWNER/REPO") }, httpStubs: func(reg *httpmock.Registry) { reg.Register( @@ -51,7 +53,7 @@ func Test_deleteRun(t *testing.T) { name: "no confirmation no tty", opts: &DeleteOptions{RepoArg: "OWNER/REPO"}, wantErr: true, - errMsg: "could not prompt: confirmation with prompt or --yes flag required", + errMsg: "could not prompt: confirmation with prompt or --confirm flag required", }, } for _, tt := range tests { diff --git a/pkg/cmd/repo/delete/http.go b/pkg/cmd/repo/delete/http.go index 2875c54bc..bd77328ac 100644 --- a/pkg/cmd/repo/delete/http.go +++ b/pkg/cmd/repo/delete/http.go @@ -15,7 +15,6 @@ func deleteRepo(client *http.Client, repo ghrepo.Interface) error { ghrepo.FullName(repo)) request, err := http.NewRequest("DELETE", url, nil) - request.Header.Set("Accept", "application/vnd.github.v3+json") if err != nil { return err } @@ -26,13 +25,8 @@ func deleteRepo(client *http.Client, repo ghrepo.Interface) error { } defer resp.Body.Close() - err = api.HandleHTTPError(resp) - if resp.StatusCode == 403 { - return fmt.Errorf(`%w - -Deletion requires authorization with the "delete_repo" scope. To authorize, run "gh auth refresh -s delete_repo"`, err) - } else if resp.StatusCode > 204 { - return err + if resp.StatusCode > 299 { + return api.HandleHTTPError(resp) } return nil From 548b39c1405ed8bf2c0888b9e27ee28c2f988cb6 Mon Sep 17 00:00:00 2001 From: meiji163 Date: Tue, 12 Oct 2021 10:48:26 -0700 Subject: [PATCH 5/7] add one test --- pkg/cmd/repo/delete/delete_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pkg/cmd/repo/delete/delete_test.go b/pkg/cmd/repo/delete/delete_test.go index 87ec0ed91..28b0133fa 100644 --- a/pkg/cmd/repo/delete/delete_test.go +++ b/pkg/cmd/repo/delete/delete_test.go @@ -55,6 +55,23 @@ func Test_deleteRun(t *testing.T) { wantErr: true, errMsg: "could not prompt: confirmation with prompt or --confirm flag required", }, + { + name: "short repo name", + opts: &DeleteOptions{RepoArg: "REPO"}, + wantStdout: "✓ Deleted repository OWNER/REPO\n", + tty: true, + askStubs: func(q *prompt.AskStubber) { + q.StubOne("OWNER/REPO") + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query UserCurrent\b`), + httpmock.StringResponse(`{"data":{"viewer":{"login":"OWNER"}}}`)) + reg.Register( + httpmock.REST("DELETE", "repos/OWNER/REPO"), + httpmock.StatusStringResponse(204, "{}")) + }, + }, } for _, tt := range tests { q, teardown := prompt.InitAskStubber() From caa282f0ba60c3a10244705d17205040c8794204 Mon Sep 17 00:00:00 2001 From: meiji163 Date: Thu, 14 Oct 2021 21:26:31 -0700 Subject: [PATCH 6/7] commit review suggestions --- pkg/cmd/repo/delete/delete.go | 25 +++++------ pkg/cmd/repo/delete/delete_test.go | 71 +++++++++++++++++++++++++++--- pkg/cmd/repo/delete/http.go | 9 +++- 3 files changed, 83 insertions(+), 22 deletions(-) diff --git a/pkg/cmd/repo/delete/delete.go b/pkg/cmd/repo/delete/delete.go index de7debd64..9dda14e2d 100644 --- a/pkg/cmd/repo/delete/delete.go +++ b/pkg/cmd/repo/delete/delete.go @@ -40,6 +40,10 @@ To authorize, run "gh auth refresh -s delete_repo"`, Args: cmdutil.ExactArgs(1, "cannot delete: repository argument required"), RunE: func(cmd *cobra.Command, args []string) error { opts.RepoArg = args[0] + if !opts.IO.CanPrompt() && !opts.Confirmed { + return &cmdutil.FlagError{ + Err: errors.New("could not prompt: confirmation with prompt or --confirm flag required")} + } if runF != nil { return runF(opts) } @@ -47,7 +51,7 @@ To authorize, run "gh auth refresh -s delete_repo"`, }, } - cmd.Flags().BoolVarP(&opts.Confirmed, "confirm", "c", false, "confirm deletion without prompting") + cmd.Flags().BoolVar(&opts.Confirmed, "confirm", false, "confirm deletion without prompting") return cmd } @@ -58,36 +62,31 @@ func deleteRun(opts *DeleteOptions) error { } apiClient := api.NewClientFromHTTP(httpClient) - deleteURL := opts.RepoArg + repoSelector := opts.RepoArg var toDelete ghrepo.Interface - if !strings.Contains(deleteURL, "/") { + if !strings.Contains(repoSelector, "/") { currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default()) if err != nil { return err } - deleteURL = currentUser + "/" + deleteURL + repoSelector = currentUser + "/" + repoSelector } - toDelete, err = ghrepo.FromFullName(deleteURL) + toDelete, err = ghrepo.FromFullName(repoSelector) if err != nil { return fmt.Errorf("argument error: %w", err) } fullName := ghrepo.FullName(toDelete) - doPrompt := opts.IO.CanPrompt() - if !opts.Confirmed && !doPrompt { - return errors.New("could not prompt: confirmation with prompt or --confirm flag required") - } - - if !opts.Confirmed && doPrompt { + if !opts.Confirmed { var valid string err := prompt.SurveyAskOne( &survey.Input{Message: fmt.Sprintf("Type %s to confirm deletion:", fullName)}, &valid, survey.WithValidator( func(val interface{}) error { - if str := val.(string); str != fullName { + if str := val.(string); !strings.EqualFold(str, fullName) { return fmt.Errorf("You entered %s", str) } return nil @@ -99,7 +98,7 @@ func deleteRun(opts *DeleteOptions) error { err = deleteRepo(httpClient, toDelete) if err != nil { - return fmt.Errorf("API call failed: %w", err) + return err } if opts.IO.IsStdoutTTY() { diff --git a/pkg/cmd/repo/delete/delete_test.go b/pkg/cmd/repo/delete/delete_test.go index 28b0133fa..d561a3269 100644 --- a/pkg/cmd/repo/delete/delete_test.go +++ b/pkg/cmd/repo/delete/delete_test.go @@ -1,15 +1,78 @@ package delete import ( + "bytes" "net/http" "testing" + "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" "github.com/cli/cli/v2/pkg/prompt" + "github.com/google/shlex" "github.com/stretchr/testify/assert" ) +func TestNewCmdDelete(t *testing.T) { + tests := []struct { + name string + input string + tty bool + output DeleteOptions + wantErr bool + errMsg string + }{ + { + name: "confirm flag", + input: "OWNER/REPO --confirm", + output: DeleteOptions{RepoArg: "OWNER/REPO", Confirmed: true}, + }, + { + name: "no confirmation no tty", + input: "OWNER/REPO", + output: DeleteOptions{RepoArg: "OWNER/REPO"}, + wantErr: true, + errMsg: "could not prompt: confirmation with prompt or --confirm flag required"}, + { + name: "no argument", + input: "", + wantErr: true, + errMsg: "cannot delete: repository argument required", + tty: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + io, _, _, _ := iostreams.Test() + io.SetStdinTTY(tt.tty) + io.SetStdoutTTY(tt.tty) + f := &cmdutil.Factory{ + IOStreams: io, + } + argv, err := shlex.Split(tt.input) + assert.NoError(t, err) + var gotOpts *DeleteOptions + cmd := NewCmdDelete(f, func(opts *DeleteOptions) error { + gotOpts = opts + return nil + }) + cmd.SetArgs(argv) + cmd.SetIn(&bytes.Buffer{}) + cmd.SetOut(&bytes.Buffer{}) + cmd.SetErr(&bytes.Buffer{}) + + _, err = cmd.ExecuteC() + if tt.wantErr { + assert.Error(t, err) + assert.Equal(t, tt.errMsg, err.Error()) + return + } + assert.NoError(t, err) + assert.Equal(t, tt.output.RepoArg, gotOpts.RepoArg) + }) + } +} + func Test_deleteRun(t *testing.T) { tests := []struct { name string @@ -27,7 +90,7 @@ func Test_deleteRun(t *testing.T) { opts: &DeleteOptions{RepoArg: "OWNER/REPO"}, wantStdout: "✓ Deleted repository OWNER/REPO\n", askStubs: func(q *prompt.AskStubber) { - // TODO: survey stubber doesn't have WithValidation support + // TODO: survey stubber doesn't have WithValidator support // so this always passes regardless of prompt input q.StubOne("OWNER/REPO") }, @@ -49,12 +112,6 @@ func Test_deleteRun(t *testing.T) { httpmock.StatusStringResponse(204, "{}")) }, }, - { - name: "no confirmation no tty", - opts: &DeleteOptions{RepoArg: "OWNER/REPO"}, - wantErr: true, - errMsg: "could not prompt: confirmation with prompt or --confirm flag required", - }, { name: "short repo name", opts: &DeleteOptions{RepoArg: "REPO"}, diff --git a/pkg/cmd/repo/delete/http.go b/pkg/cmd/repo/delete/http.go index bd77328ac..b38224fb1 100644 --- a/pkg/cmd/repo/delete/http.go +++ b/pkg/cmd/repo/delete/http.go @@ -25,8 +25,13 @@ func deleteRepo(client *http.Client, repo ghrepo.Interface) error { } defer resp.Body.Close() - if resp.StatusCode > 299 { - return api.HandleHTTPError(resp) + err = api.HandleHTTPError(resp) + + if resp.StatusCode == 403 { + return fmt.Errorf(`%w +Try authorizing the "delete_repo" scope with "gh auth refresh -s delete_repo".`, err) + } else if resp.StatusCode > 299 { + return err } return nil From f7b4588d0920b6acae952e1b25ea554e17077a2b Mon Sep 17 00:00:00 2001 From: Meijke Date: Fri, 15 Oct 2021 08:35:33 -0700 Subject: [PATCH 7/7] scope error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mislav Marohnić --- pkg/cmd/repo/delete/http.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/repo/delete/http.go b/pkg/cmd/repo/delete/http.go index b38224fb1..bd77328ac 100644 --- a/pkg/cmd/repo/delete/http.go +++ b/pkg/cmd/repo/delete/http.go @@ -25,13 +25,8 @@ func deleteRepo(client *http.Client, repo ghrepo.Interface) error { } defer resp.Body.Close() - err = api.HandleHTTPError(resp) - - if resp.StatusCode == 403 { - return fmt.Errorf(`%w -Try authorizing the "delete_repo" scope with "gh auth refresh -s delete_repo".`, err) - } else if resp.StatusCode > 299 { - return err + if resp.StatusCode > 299 { + return api.HandleHTTPError(resp) } return nil