commands/mr/checkout/mr_checkout.go (105 lines of code) (raw):

package checkout import ( "fmt" "strings" "github.com/MakeNowJust/heredoc/v2" "github.com/spf13/cobra" gitlab "gitlab.com/gitlab-org/api/client-go" "gitlab.com/gitlab-org/cli/api" "gitlab.com/gitlab-org/cli/commands/cmdutils" "gitlab.com/gitlab-org/cli/commands/mr/mrutils" "gitlab.com/gitlab-org/cli/pkg/git" ) type mrCheckoutConfig struct { branch string track bool upstream string } var mrCheckoutCfg mrCheckoutConfig func NewCmdCheckout(f *cmdutils.Factory) *cobra.Command { mrCheckoutCmd := &cobra.Command{ Use: "checkout [<id> | <branch>]", Short: "Check out an open merge request.", Long: ``, Example: heredoc.Doc(` - glab mr checkout 1 - glab mr checkout branch - glab mr checkout 12 --branch todo-fix - glab mr checkout new-feature --set-upstream-to=upstream/main Uses the checked-out branch - glab mr checkout `), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { var err error var upstream string if mrCheckoutCfg.upstream != "" { upstream = mrCheckoutCfg.upstream if val := strings.Split(mrCheckoutCfg.upstream, "/"); len(val) > 1 { // Verify that we have the remote set repo, err := f.Remotes() if err != nil { return err } _, err = repo.FindByName(val[0]) if err != nil { return err } } } apiClient, err := f.HttpClient() if err != nil { return err } mr, _, err := mrutils.MRFromArgs(f, args, "any") if err != nil { return err } if mrCheckoutCfg.branch == "" { mrCheckoutCfg.branch = mr.SourceBranch } var mrRef string var mrProject *gitlab.Project mrProject, err = api.GetProject(apiClient, mr.SourceProjectID) if err != nil { // If we don't have access to the source project, let's try the target project mrProject, err = api.GetProject(apiClient, mr.TargetProjectID) if err != nil { return err } else { // We found the target project, let's find the ref another way mrRef = fmt.Sprintf("refs/merge-requests/%d/head", mr.IID) } } else { mrRef = fmt.Sprintf("refs/heads/%s", mr.SourceBranch) } fetchRefSpec := fmt.Sprintf("%s:%s", mrRef, mrCheckoutCfg.branch) if err := git.RunCmd([]string{"fetch", mrProject.SSHURLToRepo, fetchRefSpec}); err != nil { return err } // .remote is needed for `git pull` to work // .pushRemote is needed for `git push` to work, if user has set `remote.pushDefault`. // see https://git-scm.com/docs/git-config#Documentation/git-config.txt-branchltnamegtremote if err := git.RunCmd([]string{"config", fmt.Sprintf("branch.%s.remote", mrCheckoutCfg.branch), mrProject.SSHURLToRepo}); err != nil { return err } if mr.AllowCollaboration { if err := git.RunCmd([]string{"config", fmt.Sprintf("branch.%s.pushRemote", mrCheckoutCfg.branch), mrProject.SSHURLToRepo}); err != nil { return err } } if err := git.RunCmd([]string{"config", fmt.Sprintf("branch.%s.merge", mrCheckoutCfg.branch), mrRef}); err != nil { return err } // Check out branch var gr git.StandardGitCommand if err := git.CheckoutBranch(mrCheckoutCfg.branch, gr); err != nil { return err } // Check out the branch if upstream != "" { if err := git.RunCmd([]string{"branch", "--set-upstream-to", upstream}); err != nil { return err } } return nil }, } mrCheckoutCmd.Flags().StringVarP(&mrCheckoutCfg.branch, "branch", "b", "", "Check out merge request with name <branch>.") mrCheckoutCmd.Flags().BoolVarP(&mrCheckoutCfg.track, "track", "t", true, "Set checked out branch to track the remote branch.") _ = mrCheckoutCmd.Flags().MarkDeprecated("track", "Now enabled by default") mrCheckoutCmd.Flags().StringVarP(&mrCheckoutCfg.upstream, "set-upstream-to", "u", "", "Set tracking of checked-out branch to [REMOTE/]BRANCH.") return mrCheckoutCmd }