Add pr update command

Signed-off-by: Babak K. Shandiz <babak.k.shandiz@gmail.com>
This commit is contained in:
Babak K. Shandiz 2024-04-10 19:20:44 +01:00
parent 7de10f0bdf
commit a828e05baa
No known key found for this signature in database
GPG key ID: 44950AED81AD710F

120
pkg/cmd/pr/update/update.go Normal file
View file

@ -0,0 +1,120 @@
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
`),
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.Finder = shared.NewFinder(f)
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)
}