Skip to content

Commit a8028be

Browse files
committed
add delete HTTP request and confirmation prompting
1 parent 025f86b commit a8028be

File tree

3 files changed

+101
-3
lines changed

3 files changed

+101
-3
lines changed

pkg/cmd/repo/delete/delete.go

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
package delete
22

33
import (
4+
"errors"
5+
"fmt"
46
"net/http"
7+
"strings"
58

9+
"github.com/cli/cli/v2/api"
10+
"github.com/cli/cli/v2/internal/ghinstance"
11+
"github.com/cli/cli/v2/internal/ghrepo"
612
"github.com/cli/cli/v2/pkg/cmdutil"
13+
"github.com/cli/cli/v2/pkg/prompt"
714

15+
"github.com/AlecAivazis/survey/v2"
816
"github.com/cli/cli/v2/pkg/iostreams"
917
"github.com/spf13/cobra"
1018
)
@@ -27,7 +35,8 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co
2735
Short: "Delete a repository",
2836
Long: `Delete a GitHub repository.
2937
30-
Ensure that you have authorized the \"delete_repo\" scope: gh auth refresh -h github.com -s delete_repo"`,
38+
Deletion requires authorization with the "delete_repo" scope.
39+
To authorize, run "gh auth refresh -h github.com -s delete_repo"`,
3140
Args: cmdutil.ExactArgs(1, "cannot delete: repository argument required"),
3241
RunE: func(cmd *cobra.Command, args []string) error {
3342
opts.RepoArg = args[0]
@@ -38,11 +47,68 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co
3847
},
3948
}
4049

41-
cmd.Flags().BoolVar(&opts.Confirmed, "yes", false, "Confirm deletion without prompting")
50+
cmd.Flags().BoolVar(&opts.Confirmed, "yes", false, "confirm deletion without prompting")
4251
return cmd
4352
}
4453

4554
func deleteRun(opts *DeleteOptions) error {
55+
httpClient, err := opts.HttpClient()
56+
if err != nil {
57+
return err
58+
}
59+
apiClient := api.NewClientFromHTTP(httpClient)
60+
61+
deleteURL := opts.RepoArg
62+
var toDelete ghrepo.Interface
63+
64+
if !strings.Contains(deleteURL, "/") {
65+
currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default())
66+
if err != nil {
67+
return err
68+
}
69+
deleteURL = currentUser + "/" + deleteURL
70+
}
71+
toDelete, err = ghrepo.FromFullName(deleteURL)
72+
if err != nil {
73+
return fmt.Errorf("argument error: %w", err)
74+
}
75+
76+
fullName := ghrepo.FullName(toDelete)
77+
78+
doPrompt := opts.IO.CanPrompt()
79+
if !opts.Confirmed && !doPrompt {
80+
return errors.New("could not prompt: confirmation with prompt or --yes flag required")
81+
}
82+
83+
if !opts.Confirmed && doPrompt {
84+
var valid string
85+
err := prompt.SurveyAskOne(
86+
&survey.Input{Message: fmt.Sprintf("Type %s to confirm deletion:", fullName)},
87+
&valid,
88+
survey.WithValidator(
89+
func(val interface{}) error {
90+
if str := val.(string); str != fullName {
91+
return fmt.Errorf("You entered %s", str)
92+
}
93+
return nil
94+
}))
95+
if err != nil {
96+
return fmt.Errorf("could not prompt: %w", err)
97+
}
98+
}
99+
100+
err = deleteRepo(httpClient, toDelete)
101+
if err != nil {
102+
return fmt.Errorf("API call failed: %w", err)
103+
}
104+
105+
if opts.IO.IsStdoutTTY() {
106+
cs := opts.IO.ColorScheme()
107+
fmt.Fprintf(opts.IO.Out,
108+
"%s Deleted repository %s\n",
109+
cs.SuccessIcon(),
110+
fullName)
111+
}
46112

47113
return nil
48114
}

pkg/cmd/repo/delete/http.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,39 @@
11
package delete
22

33
import (
4+
"fmt"
45
"net/http"
6+
7+
"github.com/cli/cli/v2/api"
8+
"github.com/cli/cli/v2/internal/ghinstance"
9+
"github.com/cli/cli/v2/internal/ghrepo"
510
)
611

7-
func deleteRepo(client *http.Client) error {
12+
func deleteRepo(client *http.Client, repo ghrepo.Interface) error {
13+
url := fmt.Sprintf("%srepos/%s",
14+
ghinstance.RESTPrefix(repo.RepoHost()),
15+
ghrepo.FullName(repo))
16+
17+
request, err := http.NewRequest("DELETE", url, nil)
18+
request.Header.Set("Accept", "application/vnd.github.v3+json")
19+
if err != nil {
20+
return err
21+
}
22+
23+
resp, err := client.Do(request)
24+
if err != nil {
25+
return err
26+
}
27+
defer resp.Body.Close()
28+
29+
err = api.HandleHTTPError(resp)
30+
if resp.StatusCode == 403 {
31+
return fmt.Errorf(`%w
32+
33+
Deletion requires authorization with the "delete_repo" scope. To authorize, run "gh auth refresh -s delete_repo"`, err)
34+
} else if resp.StatusCode > 204 {
35+
return err
36+
}
837

38+
return nil
939
}

pkg/cmd/repo/repo.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
repoCloneCmd "github.com/cli/cli/v2/pkg/cmd/repo/clone"
66
repoCreateCmd "github.com/cli/cli/v2/pkg/cmd/repo/create"
77
creditsCmd "github.com/cli/cli/v2/pkg/cmd/repo/credits"
8+
repoDeleteCmd "github.com/cli/cli/v2/pkg/cmd/repo/delete"
89
repoForkCmd "github.com/cli/cli/v2/pkg/cmd/repo/fork"
910
gardenCmd "github.com/cli/cli/v2/pkg/cmd/repo/garden"
1011
repoListCmd "github.com/cli/cli/v2/pkg/cmd/repo/list"
@@ -42,6 +43,7 @@ func NewCmdRepo(f *cmdutil.Factory) *cobra.Command {
4243
cmd.AddCommand(repoSyncCmd.NewCmdSync(f, nil))
4344
cmd.AddCommand(creditsCmd.NewCmdRepoCredits(f, nil))
4445
cmd.AddCommand(gardenCmd.NewCmdGarden(f, nil))
46+
cmd.AddCommand(repoDeleteCmd.NewCmdDelete(f, nil))
4547

4648
return cmd
4749
}

0 commit comments

Comments
 (0)