checkout.go 2.9 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
	"github.com/jingweno/gh/git"
J
Jingwen Owen Ou 已提交
6
	"github.com/jingweno/gh/github"
J
Jingwen Owen Ou 已提交
7
	"github.com/jingweno/gh/utils"
J
Jingwen Owen Ou 已提交
8
	"regexp"
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
}

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

  $ gh checkout https://github.com/jingweno/gh/pull/73 custom-branch-name
**/
J
Jingwen Owen Ou 已提交
30
func checkout(command *Command, args *Args) {
J
Jingwen Owen Ou 已提交
31
	var err error
J
Jingwen Owen Ou 已提交
32 33
	if !args.IsEmpty() {
		err = transformCheckoutArgs(args)
34
		utils.Fatal(err)
J
Jingwen Owen Ou 已提交
35 36 37
	}
}

J
Jingwen Owen Ou 已提交
38 39
func transformCheckoutArgs(args *Args) error {
	id := parsePullRequestId(args.First())
J
Jingwen Owen Ou 已提交
40
	if id != "" {
J
Jingwen Owen Ou 已提交
41
		url := args.Remove(0)
J
Jingwen Owen Ou 已提交
42 43 44
		gh := github.New()
		pullRequest, err := gh.PullRequest(id)
		if err != nil {
J
Jingwen Owen Ou 已提交
45
			return err
J
Jingwen Owen Ou 已提交
46 47 48 49 50
		}

		user := pullRequest.User.Login
		branch := pullRequest.Head.Ref
		if pullRequest.Head.Repo.ID == 0 {
J
Jingwen Owen Ou 已提交
51
			return fmt.Errorf("%s's fork is not available anymore", user)
J
Jingwen Owen Ou 已提交
52
		}
53

J
Jingwen Owen Ou 已提交
54
		remoteExists, err := checkIfRemoteExists(user)
J
Jingwen Owen Ou 已提交
55
		if err != nil {
J
Jingwen Owen Ou 已提交
56
			return err
J
Jingwen Owen Ou 已提交
57 58
		}

J
Jingwen Owen Ou 已提交
59
		if remoteExists {
60
			updateExistingRemote(args, user, branch)
61
		} else {
62 63 64 65
			err = addRmote(args, user, branch, url, pullRequest.Head.Repo.Private)
			if err != nil {
				return err
			}
66
		}
J
Jingwen Owen Ou 已提交
67 68

		var newBranchName string
J
Jingwen Owen Ou 已提交
69 70
		if args.Size() > 0 {
			newBranchName = args.Remove(0)
J
Jingwen Owen Ou 已提交
71 72 73
		} else {
			newBranchName = fmt.Sprintf("%s-%s", user, branch)
		}
J
Jingwen Owen Ou 已提交
74
		trackedBranch := fmt.Sprintf("%s/%s", user, branch)
J
Jingwen Owen Ou 已提交
75

J
Jingwen Owen Ou 已提交
76
		args.Append("--track", "-B", newBranchName, trackedBranch)
J
Jingwen Owen Ou 已提交
77

J
Jingwen Owen Ou 已提交
78
		return nil
J
Jingwen Owen Ou 已提交
79 80
	}

J
Jingwen Owen Ou 已提交
81
	return nil
J
Jingwen Owen Ou 已提交
82 83 84 85 86 87 88 89 90
}

func parsePullRequestId(url string) string {
	pullURLRegex := regexp.MustCompile("https://github\\.com/.+/.+/pull/(\\d+)")
	if pullURLRegex.MatchString(url) {
		return pullURLRegex.FindStringSubmatch(url)[1]
	}

	return ""
J
Jingwen Owen Ou 已提交
91
}
J
Jingwen Owen Ou 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

func checkIfRemoteExists(remote string) (bool, error) {
	remotes, err := git.Remotes()
	if err != nil {
		return false, err
	}

	for _, r := range remotes {
		if r.Name == remote {
			return true, nil
		}
	}

	return false, nil
}

108 109
func updateExistingRemote(args *Args, user, branch string) {
	args.Before("git", "remote", "set-branches", "--add", user, branch)
J
Jingwen Owen Ou 已提交
110
	remoteURL := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branch, user, branch)
111
	args.Before("git", "fetch", user, remoteURL)
J
Jingwen Owen Ou 已提交
112 113
}

114
func addRmote(args *Args, user, branch, url string, isPrivate bool) error {
J
Jingwen Owen Ou 已提交
115 116 117 118 119 120
	project, err := github.ParseProjectFromURL(url)
	if err != nil {
		return err
	}

	sshURL := project.GitURL("", user, isPrivate)
121
	args.Before("git", "remote", "add", "-f", "-t", branch, user, sshURL)
J
Jingwen Owen Ou 已提交
122

123
	return nil
J
Jingwen Owen Ou 已提交
124
}