checkout.go 2.7 KB
Newer Older
J
Jingwen Owen Ou 已提交
1 2
package commands

J
Jingwen Owen Ou 已提交
3
import (
J
Jingwen Owen Ou 已提交
4
	"fmt"
J
Jingwen Owen Ou 已提交
5 6
	"regexp"

J
Jingwen Owen Ou 已提交
7 8
	"github.com/github/hub/github"
	"github.com/github/hub/utils"
J
Jingwen Owen Ou 已提交
9 10
)

J
Jingwen Owen Ou 已提交
11 12 13 14 15
var cmdCheckout = &Command{
	Run:          checkout,
	GitExtension: true,
	Usage:        "checkout PULLREQ-URL [BRANCH]",
	Short:        "Switch the active branch to another branch",
16 17 18 19 20
	Long: `Checks out the head of the pull request as a local branch, to allow for
reviewing, rebasing and otherwise cleaning up the commits in the pull
request before merging. The name of the local branch can explicitly be
set with BRANCH.
`,
J
Jingwen Owen Ou 已提交
21 22
}

23 24 25 26
func init() {
	CmdRunner.Use(cmdCheckout)
}

J
Jingwen Owen Ou 已提交
27 28
/**
  $ gh checkout https://github.com/jingweno/gh/pull/73
29 30
  > git remote add -f -t feature git://github:com/foo/gh.git
  > git checkout --track -B foo-feature foo/feature
J
Jingwen Owen Ou 已提交
31 32 33

  $ gh checkout https://github.com/jingweno/gh/pull/73 custom-branch-name
**/
J
Jingwen Owen Ou 已提交
34
func checkout(command *Command, args *Args) {
J
Jingwen Owen Ou 已提交
35
	if !args.IsParamsEmpty() {
J
Jingwen Owen Ou 已提交
36
		err := transformCheckoutArgs(args)
J
Jingwen Owen Ou 已提交
37
		utils.Check(err)
J
Jingwen Owen Ou 已提交
38 39 40
	}
}

J
Jingwen Owen Ou 已提交
41
func transformCheckoutArgs(args *Args) error {
42
	words := args.Words()
J
Jingwen Owen Ou 已提交
43

44 45 46
	if len(words) == 0 {
		return nil
	}
J
Jingwen Owen Ou 已提交
47

48 49 50 51
	checkoutURL := words[0]
	var newBranchName string
	if len(words) > 1 {
		newBranchName = words[1]
52
	}
J
Jingwen Owen Ou 已提交
53 54 55 56 57 58

	url, err := github.ParseURL(checkoutURL)
	if err != nil {
		// not a valid GitHub URL
		return nil
	}
59

60 61 62
	pullURLRegex := regexp.MustCompile("^pull/(\\d+)")
	projectPath := url.ProjectPath()
	if !pullURLRegex.MatchString(projectPath) {
J
Jingwen Owen Ou 已提交
63
		// not a valid PR URL
64 65
		return nil
	}
J
Jingwen Owen Ou 已提交
66

67
	id := pullURLRegex.FindStringSubmatch(projectPath)[1]
J
Jingwen Owen Ou 已提交
68 69
	gh := github.NewClient(url.Project.Host)
	pullRequest, err := gh.PullRequest(url.Project, id)
70 71 72
	if err != nil {
		return err
	}
J
Jingwen Owen Ou 已提交
73

74 75 76
	if idx := args.IndexOfParam(newBranchName); idx >= 0 {
		args.RemoveParam(idx)
	}
J
Jingwen Owen Ou 已提交
77

78
	user, branch := parseUserBranchFromPR(pullRequest)
79
	if pullRequest.Head.Repo == nil {
80
		return fmt.Errorf("Error: %s's fork is not available anymore", user)
81 82
	}

83
	if newBranchName == "" {
84
		newBranchName = fmt.Sprintf("%s-%s", user, branch)
J
Jingwen Owen Ou 已提交
85
	}
86

87 88 89
	repo, err := github.LocalRepo()
	utils.Check(err)

J
Jingwen Owen Ou 已提交
90
	_, err = repo.RemoteByName(user)
91 92 93 94 95
	if err == nil {
		args.Before("git", "remote", "set-branches", "--add", user, branch)
		remoteURL := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branch, user, branch)
		args.Before("git", "fetch", user, remoteURL)
	} else {
96
		u := url.Project.GitURL(pullRequest.Head.Repo.Name, user, pullRequest.Head.Repo.Private)
97 98
		args.Before("git", "remote", "add", "-f", "-t", branch, user, u)
	}
J
Jingwen Owen Ou 已提交
99

100 101
	remoteName := fmt.Sprintf("%s/%s", user, branch)
	replaceCheckoutParam(args, checkoutURL, newBranchName, remoteName)
J
Jingwen Owen Ou 已提交
102

103
	return nil
J
Jingwen Owen Ou 已提交
104
}
105 106 107 108 109 110

func replaceCheckoutParam(args *Args, checkoutURL, branchName, remoteName string) {
	idx := args.IndexOfParam(checkoutURL)
	args.RemoveParam(idx)
	args.InsertParam(idx, "--track", "-B", branchName, remoteName)
}