mirror of https://gitlab.com/gitlab-org/cli.git
129 lines
3.8 KiB
Go
129 lines
3.8 KiB
Go
package checkout
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/MakeNowJust/heredoc"
|
|
"github.com/spf13/cobra"
|
|
"github.com/xanzy/go-gitlab"
|
|
"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: "Checkout to 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
|
|
glab mr checkout # use checked out branch
|
|
`),
|
|
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
|
|
if err := git.CheckoutBranch(mrCheckoutCfg.branch); 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", "", "checkout merge request with <branch> name")
|
|
mrCheckoutCmd.Flags().BoolVarP(&mrCheckoutCfg.track, "track", "t", true, "set checked out branch to track 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
|
|
}
|