gitlab.com/prarit/lab@v0.14.0/cmd/mr_checkout.go (about) 1 package cmd 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/spf13/cobra" 8 "github.com/tcnksm/go-gitconfig" 9 "github.com/xanzy/go-gitlab" 10 "github.com/zaquestion/lab/internal/git" 11 lab "github.com/zaquestion/lab/internal/gitlab" 12 ) 13 14 // mrCheckoutConfig holds configuration values for calls to lab mr checkout 15 type mrCheckoutConfig struct { 16 branch string 17 track bool 18 } 19 20 var ( 21 mrCheckoutCfg mrCheckoutConfig 22 ) 23 24 // listCmd represents the list command 25 var checkoutCmd = &cobra.Command{ 26 Use: "checkout", 27 Short: "Checkout an open merge request", 28 Long: ``, 29 Args: cobra.ExactArgs(1), 30 Run: func(cmd *cobra.Command, args []string) { 31 rn, mrID, err := parseArgs(args) 32 if err != nil { 33 log.Fatal(err) 34 } 35 36 mrs, err := lab.MRList(rn, gitlab.ListProjectMergeRequestsOptions{ 37 IIDs: []int{int(mrID)}, 38 }, 1) 39 if err != nil { 40 log.Fatal(err) 41 } 42 if len(mrs) < 1 { 43 fmt.Printf("MR #%d not found\n", mrID) 44 return 45 } 46 47 mr := mrs[0] 48 // If the config does not specify a branch, use the mr source branch name 49 if mrCheckoutCfg.branch == "" { 50 mrCheckoutCfg.branch = mr.SourceBranch 51 } 52 // By default, fetch to configured branch 53 fetchToRef := mrCheckoutCfg.branch 54 55 // If track, make sure we have a remote for the mr author and then set 56 // the fetchToRef to the mr author/sourceBranch 57 if mrCheckoutCfg.track { 58 // Check if remote already exists 59 if _, err := gitconfig.Local("remote." + mr.Author.Username + ".url"); err != nil { 60 // Find and create remote 61 mrProject, err := lab.GetProject(mr.SourceProjectID) 62 if err != nil { 63 log.Fatal(err) 64 } 65 if err := git.RemoteAdd(mr.Author.Username, mrProject.SSHURLToRepo, "."); err != nil { 66 log.Fatal(err) 67 } 68 } 69 fetchToRef = fmt.Sprintf("refs/remotes/%s/%s", mr.Author.Username, mr.SourceBranch) 70 } 71 72 // https://docs.gitlab.com/ce/user/project/merge_requests/#checkout-merge-requests-locally 73 mrRef := fmt.Sprintf("refs/merge-requests/%d/head", mrID) 74 fetchRefSpec := fmt.Sprintf("%s:%s", mrRef, fetchToRef) 75 if err := git.New("fetch", forkedFromRemote, fetchRefSpec).Run(); err != nil { 76 log.Fatal(err) 77 } 78 79 if mrCheckoutCfg.track { 80 // Create configured branch with tracking from fetchToRef 81 // git branch --flags <branchname> [<start-point>] 82 if err := git.New("branch", "--track", mrCheckoutCfg.branch, fetchToRef).Run(); err != nil { 83 log.Fatal(err) 84 } 85 } 86 87 // Check out branch 88 if err := git.New("checkout", mrCheckoutCfg.branch).Run(); err != nil { 89 log.Fatal(err) 90 } 91 }, 92 } 93 94 func init() { 95 checkoutCmd.Flags().StringVarP(&mrCheckoutCfg.branch, "branch", "b", "", "checkout merge request with <branch> name") 96 checkoutCmd.Flags().BoolVarP(&mrCheckoutCfg.track, "track", "t", false, "set checked out branch to track mr author remote branch, adds remote if needed") 97 mrCmd.AddCommand(checkoutCmd) 98 }