github.com/jingweno/gh@v2.1.1-0.20221007190738-04a7985fa9a1+incompatible/commands/checkout.go (about) 1 package commands 2 3 import ( 4 "fmt" 5 "github.com/jingweno/gh/github" 6 "github.com/jingweno/gh/utils" 7 "regexp" 8 ) 9 10 var cmdCheckout = &Command{ 11 Run: checkout, 12 GitExtension: true, 13 Usage: "checkout PULLREQ-URL [BRANCH]", 14 Short: "Switch the active branch to another branch", 15 Long: `Checks out the head of the pull request as a local branch, to allow for 16 reviewing, rebasing and otherwise cleaning up the commits in the pull 17 request before merging. The name of the local branch can explicitly be 18 set with BRANCH. 19 `, 20 } 21 22 func init() { 23 CmdRunner.Use(cmdCheckout) 24 } 25 26 /** 27 $ gh checkout https://github.com/jingweno/gh/pull/73 28 > git remote add -f -t feature git://github:com/foo/gh.git 29 > git checkout --track -B foo-feature foo/feature 30 31 $ gh checkout https://github.com/jingweno/gh/pull/73 custom-branch-name 32 **/ 33 func checkout(command *Command, args *Args) { 34 if !args.IsParamsEmpty() { 35 err := transformCheckoutArgs(args) 36 utils.Check(err) 37 } 38 } 39 40 func transformCheckoutArgs(args *Args) error { 41 words := args.Words() 42 if len(words) == 0 { 43 return nil 44 } 45 46 checkoutURL := words[0] 47 url, err := github.ParseURL(checkoutURL) 48 if err != nil { 49 return nil 50 } 51 var newBranchName string 52 if len(words) > 1 { 53 newBranchName = words[1] 54 } 55 56 pullURLRegex := regexp.MustCompile("^pull/(\\d+)") 57 projectPath := url.ProjectPath() 58 if !pullURLRegex.MatchString(projectPath) { 59 return nil 60 } 61 62 id := pullURLRegex.FindStringSubmatch(projectPath)[1] 63 gh := github.NewClient(url.Project.Host) 64 pullRequest, err := gh.PullRequest(url.Project, id) 65 if err != nil { 66 return err 67 } 68 69 if idx := args.IndexOfParam(newBranchName); idx >= 0 { 70 args.RemoveParam(idx) 71 } 72 73 user, branch := parseUserBranchFromPR(pullRequest) 74 if pullRequest.Head.Repo.ID == 0 { 75 return fmt.Errorf("Error: %s's fork is not available anymore", user) 76 } 77 78 if newBranchName == "" { 79 newBranchName = fmt.Sprintf("%s-%s", user, branch) 80 } 81 82 repo := github.LocalRepo() 83 _, err = repo.RemoteByName(user) 84 if err == nil { 85 args.Before("git", "remote", "set-branches", "--add", user, branch) 86 remoteURL := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branch, user, branch) 87 args.Before("git", "fetch", user, remoteURL) 88 } else { 89 u := url.Project.GitURL("", user, pullRequest.Head.Repo.Private) 90 args.Before("git", "remote", "add", "-f", "-t", branch, user, u) 91 } 92 93 idx := args.IndexOfParam(checkoutURL) 94 args.RemoveParam(idx) 95 args.InsertParam(idx, "--track", "-B", newBranchName, fmt.Sprintf("%s/%s", user, branch)) 96 97 return nil 98 }