X Tutup
Skip to content

Commit b9292f5

Browse files
author
Nate Smith
authored
Merge pull request cli#1476 from rimazk123/prclose-delete
Add delete branch flag to pr close
2 parents ddfa171 + e44eb66 commit b9292f5

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

pkg/cmd/pr/close/close.go

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net/http"
66

77
"github.com/cli/cli/api"
8+
"github.com/cli/cli/git"
89
"github.com/cli/cli/internal/config"
910
"github.com/cli/cli/internal/ghrepo"
1011
"github.com/cli/cli/pkg/cmd/pr/shared"
@@ -19,15 +20,19 @@ type CloseOptions struct {
1920
Config func() (config.Config, error)
2021
IO *iostreams.IOStreams
2122
BaseRepo func() (ghrepo.Interface, error)
23+
Branch func() (string, error)
2224

23-
SelectorArg string
25+
SelectorArg string
26+
DeleteBranch bool
27+
DeleteLocalBranch bool
2428
}
2529

2630
func NewCmdClose(f *cmdutil.Factory, runF func(*CloseOptions) error) *cobra.Command {
2731
opts := &CloseOptions{
2832
IO: f.IOStreams,
2933
HttpClient: f.HttpClient,
3034
Config: f.Config,
35+
Branch: f.Branch,
3136
}
3237

3338
cmd := &cobra.Command{
@@ -42,12 +47,15 @@ func NewCmdClose(f *cmdutil.Factory, runF func(*CloseOptions) error) *cobra.Comm
4247
opts.SelectorArg = args[0]
4348
}
4449

50+
opts.DeleteLocalBranch = !cmd.Flags().Changed("repo")
51+
4552
if runF != nil {
4653
return runF(opts)
4754
}
4855
return closeRun(opts)
4956
},
5057
}
58+
cmd.Flags().BoolVarP(&opts.DeleteBranch, "delete-branch", "d", false, "Delete the local and remote branch after close")
5159

5260
return cmd
5361
}
@@ -79,5 +87,52 @@ func closeRun(opts *CloseOptions) error {
7987

8088
fmt.Fprintf(opts.IO.ErrOut, "%s Closed pull request #%d (%s)\n", utils.Red("✔"), pr.Number, pr.Title)
8189

90+
crossRepoPR := pr.HeadRepositoryOwner.Login != baseRepo.RepoOwner()
91+
92+
if opts.DeleteBranch {
93+
branchSwitchString := ""
94+
95+
if opts.DeleteLocalBranch && !crossRepoPR {
96+
currentBranch, err := opts.Branch()
97+
if err != nil {
98+
return err
99+
}
100+
101+
var branchToSwitchTo string
102+
if currentBranch == pr.HeadRefName {
103+
branchToSwitchTo, err = api.RepoDefaultBranch(apiClient, baseRepo)
104+
if err != nil {
105+
return err
106+
}
107+
err = git.CheckoutBranch(branchToSwitchTo)
108+
if err != nil {
109+
return err
110+
}
111+
}
112+
113+
localBranchExists := git.HasLocalBranch(pr.HeadRefName)
114+
if localBranchExists {
115+
err = git.DeleteLocalBranch(pr.HeadRefName)
116+
if err != nil {
117+
err = fmt.Errorf("failed to delete local branch %s: %w", utils.Cyan(pr.HeadRefName), err)
118+
return err
119+
}
120+
}
121+
122+
if branchToSwitchTo != "" {
123+
branchSwitchString = fmt.Sprintf(" and switched to branch %s", utils.Cyan(branchToSwitchTo))
124+
}
125+
}
126+
127+
if !crossRepoPR {
128+
err = api.BranchDeleteRemote(apiClient, baseRepo, pr.HeadRefName)
129+
if err != nil {
130+
err = fmt.Errorf("failed to delete remote branch %s: %w", utils.Cyan(pr.HeadRefName), err)
131+
return err
132+
}
133+
}
134+
fmt.Fprintf(opts.IO.ErrOut, "%s Deleted branch %s%s\n", utils.Red("✔"), utils.Cyan(pr.HeadRefName), branchSwitchString)
135+
}
136+
82137
return nil
83138
}

pkg/cmd/pr/close/close_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, err
3333
BaseRepo: func() (ghrepo.Interface, error) {
3434
return ghrepo.New("OWNER", "REPO"), nil
3535
},
36+
Branch: func() (string, error) {
37+
return "trunk", nil
38+
},
3639
}
3740

3841
cmd := NewCmdClose(factory, nil)
@@ -99,3 +102,32 @@ func TestPrClose_alreadyClosed(t *testing.T) {
99102
t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr())
100103
}
101104
}
105+
106+
func TestPrClose_deleteBranch(t *testing.T) {
107+
http := &httpmock.Registry{}
108+
defer http.Verify(t)
109+
http.StubResponse(200, bytes.NewBufferString(`
110+
{ "data": { "repository": {
111+
"pullRequest": { "number": 96, "title": "The title of the PR", "headRefName":"blueberries", "headRepositoryOwner": {"login": "OWNER"}}
112+
} } }
113+
`))
114+
http.StubResponse(200, bytes.NewBufferString(`{"id": "THE-ID"}`))
115+
http.Register(
116+
httpmock.REST("DELETE", "repos/OWNER/REPO/git/refs/heads/blueberries"),
117+
httpmock.StringResponse(`{}`))
118+
119+
cs, cmdTeardown := test.InitCmdStubber()
120+
defer cmdTeardown()
121+
122+
cs.Stub("") // git config --get-regexp ^branch\.blueberries\.(remote|merge)$
123+
cs.Stub("") // git rev-parse --verify blueberries`
124+
cs.Stub("") // git branch -d
125+
cs.Stub("") // git push origin --delete blueberries
126+
127+
output, err := runCommand(http, true, `96 --delete-branch`)
128+
if err != nil {
129+
t.Fatalf("Got unexpected error running `pr close` %s", err)
130+
}
131+
132+
test.ExpectLines(t, output.Stderr(), `Closed pull request #96 \(The title of the PR\)`, `Deleted branch blueberries`)
133+
}

0 commit comments

Comments
 (0)
X Tutup