125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package update
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/MakeNowJust/heredoc"
|
|
"github.com/cli/cli/v2/api"
|
|
"github.com/cli/cli/v2/git"
|
|
"github.com/cli/cli/v2/internal/ghrepo"
|
|
shared "github.com/cli/cli/v2/pkg/cmd/pr/shared"
|
|
"github.com/cli/cli/v2/pkg/cmdutil"
|
|
"github.com/cli/cli/v2/pkg/iostreams"
|
|
"github.com/shurcooL/githubv4"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
type UpdateOptions struct {
|
|
HttpClient func() (*http.Client, error)
|
|
IO *iostreams.IOStreams
|
|
GitClient *git.Client
|
|
|
|
Finder shared.PRFinder
|
|
|
|
SelectorArg string
|
|
Rebase bool
|
|
}
|
|
|
|
func NewCmdUpdate(f *cmdutil.Factory, runF func(*UpdateOptions) error) *cobra.Command {
|
|
opts := &UpdateOptions{
|
|
IO: f.IOStreams,
|
|
HttpClient: f.HttpClient,
|
|
GitClient: f.GitClient,
|
|
}
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "update [<number> | <url> | <branch>]",
|
|
Short: "Update a pull request branch",
|
|
Long: heredoc.Docf(`
|
|
Update a pull request branch with latest changes of the base branch.
|
|
|
|
Without an argument, the pull request that belongs to the current branch is selected.
|
|
|
|
The default behavior is to update with a merge commit (i.e., merging the base branch
|
|
into the the PR's branch). To reconcile the changes with rebasing on top of the base
|
|
branch, the %[1]s--rebase%[1]s option should be provided.
|
|
`, "`"),
|
|
Example: heredoc.Doc(`
|
|
$ gh pr update 23
|
|
$ gh pr update 23 --rebase
|
|
$ gh pr update 23 --repo owner/repo
|
|
`),
|
|
Args: cobra.MaximumNArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
opts.Finder = shared.NewFinder(f)
|
|
|
|
if repoOverride, _ := cmd.Flags().GetString("repo"); repoOverride != "" && len(args) == 0 {
|
|
return cmdutil.FlagErrorf("argument required when using the --repo flag")
|
|
}
|
|
|
|
if len(args) > 0 {
|
|
opts.SelectorArg = args[0]
|
|
}
|
|
|
|
if runF != nil {
|
|
return runF(opts)
|
|
}
|
|
|
|
return updateRun(opts)
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&opts.Rebase, "rebase", false, "Update PR branch by rebasing on top of latest base branch")
|
|
|
|
_ = cmdutil.RegisterBranchCompletionFlags(f.GitClient, cmd, "base")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func updateRun(opts *UpdateOptions) error {
|
|
findOptions := shared.FindOptions{
|
|
Selector: opts.SelectorArg,
|
|
Fields: []string{"id", "headRefOid"},
|
|
}
|
|
|
|
pr, repo, err := opts.Finder.Find(findOptions)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
httpClient, err := opts.HttpClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
apiClient := api.NewClientFromHTTP(httpClient)
|
|
|
|
opts.IO.StartProgressIndicator()
|
|
err = updatePullRequestBranch(apiClient, repo, pr.ID, pr.HeadRefOid, opts.Rebase)
|
|
opts.IO.StopProgressIndicator()
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cs := opts.IO.ColorScheme()
|
|
fmt.Fprintf(opts.IO.ErrOut, "%s PR branch updated\n", cs.SuccessIcon())
|
|
return nil
|
|
}
|
|
|
|
// updatePullRequestBranch calls the GraphQL API endpoint to update the given PR
|
|
// branch with latest changes of its base.
|
|
func updatePullRequestBranch(apiClient *api.Client, repo ghrepo.Interface, pullRequestID string, expectedHeadOid string, rebase bool) error {
|
|
updateMethod := githubv4.PullRequestBranchUpdateMethodMerge
|
|
if rebase {
|
|
updateMethod = githubv4.PullRequestBranchUpdateMethodRebase
|
|
}
|
|
|
|
params := githubv4.UpdatePullRequestBranchInput{
|
|
PullRequestID: pullRequestID,
|
|
ExpectedHeadOid: (*githubv4.GitObjectID)(&expectedHeadOid),
|
|
UpdateMethod: &updateMethod,
|
|
}
|
|
|
|
return api.UpdatePullRequestBranch(apiClient, repo, params)
|
|
}
|