-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathmerge.go
More file actions
113 lines (97 loc) · 2.84 KB
/
Copy pathmerge.go
File metadata and controls
113 lines (97 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package cmd
import (
"fmt"
"github.com/cli/go-gh/v2/pkg/browser"
"github.com/github/gh-stack/internal/prompter"
"github.com/github/gh-stack/internal/config"
"github.com/github/gh-stack/internal/stack"
"github.com/spf13/cobra"
)
func MergeCmd(cfg *config.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "merge [<pr-or-branch>]",
Short: "Merge a stack of PRs",
Long: `Merges the specified PR and all PRs below it in the stack.
Accepts a PR URL, PR number, or branch name. When run without
arguments, operates on the current branch's PR.`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var target string
if len(args) > 0 {
target = args[0]
}
return runMerge(cfg, target)
},
}
return cmd
}
func runMerge(cfg *config.Config, target string) error {
// Standard stack loading and validation.
result, err := loadStack(cfg, "")
if err != nil {
return ErrNotInStack
}
s := result.Stack
currentBranch := result.CurrentBranch
// Sync PR state from GitHub so merge status is up to date.
syncStackPRs(cfg, s)
// Persist the refreshed PR state.
stack.SaveNonBlocking(result.GitDir, result.StackFile)
// Resolve which branch to operate on.
var br *stack.BranchRef
if target != "" {
_, br, err = resolvePR(cfg, result.StackFile, target)
if err != nil {
cfg.Errorf("%s", err)
return ErrNotInStack
}
} else {
idx := s.IndexOf(currentBranch)
if idx < 0 {
if s.IsFullyMerged() {
cfg.Successf("All PRs in this stack have already been merged")
return nil
}
cfg.Errorf("current branch %q is not a stack branch (it may be the trunk)", currentBranch)
return ErrNotInStack
}
br = &s.Branches[idx]
}
if br.PullRequest == nil {
cfg.Errorf("no pull request found for branch %q", br.Branch)
cfg.Printf(" Run %s to create PRs for this stack.", cfg.ColorCyan("gh stack submit"))
return ErrSilent
}
if br.IsMerged() {
cfg.Successf("PR %s has already been merged", cfg.PRLink(br.PullRequest.Number, br.PullRequest.URL))
cfg.Printf(" %s", br.PullRequest.URL)
return nil
}
prURL := br.PullRequest.URL
prLink := cfg.PRLink(br.PullRequest.Number, prURL)
cfg.Warningf("Merging stacked PRs from the CLI is not yet supported")
if cfg.IsInteractive() {
p := prompter.New(cfg.In, cfg.Out, cfg.Err)
openWeb, promptErr := p.Confirm(
fmt.Sprintf("Open %s in your browser?", prLink), true)
if promptErr != nil {
if isInterruptError(promptErr) {
printInterrupt(cfg)
return nil
}
cfg.Errorf("prompt failed: %s", promptErr)
return nil
}
if openWeb {
b := browser.New("", cfg.Out, cfg.Err)
if err := b.Browse(prURL); err != nil {
cfg.Warningf("failed to open browser: %s", err)
} else {
cfg.Successf("Opened %s in your browser", prLink)
return nil
}
}
}
cfg.Printf(" You can merge this PR at: %s", prURL)
return nil
}