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
	"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 16 17
var cmdCheckout = &Command{
	Run:          checkout,
	GitExtension: true,
	Usage:        "checkout PULLREQ-URL [BRANCH]",
	Short:        "Switch the active branch to another branch",
}

J
Jingwen Owen Ou 已提交
18 19 20 21 22 23 24
/**
  $ gh checkout https://github.com/jingweno/gh/pull/73
  # > git remote add -f -t feature git://github:com/foo/gh.git
  # > git checkout --track -B foo-feature foo/feature

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

J
Jingwen Owen Ou 已提交
32
	err = git.SysExec("checkout", args.Array()...)
J
Jingwen Owen Ou 已提交
33 34 35
	utils.Check(err)
}

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

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

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

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

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

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

J
Jingwen Owen Ou 已提交
76
		return nil
J
Jingwen Owen Ou 已提交
77 78
	}

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

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 已提交
89
}
J
Jingwen Owen Ou 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

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
}

func updateExistingRemote(user, branch string) error {
	err := git.Spawn("remote", "set-branches", "--add", user, branch)
	if err != nil {
		return err
	}
	remoteURL := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branch, user, branch)

	return git.Spawn("fetch", user, remoteURL)
}

func addRmote(user, branch, url string, isPrivate bool) error {
	project, err := github.ParseProjectFromURL(url)
	if err != nil {
		return err
	}

	sshURL := project.GitURL("", user, isPrivate)

	return git.Spawn("remote", "add", "-f", "-t", branch, user, sshURL)
}