2013-06-21 22:40:42 +04:00
|
|
|
package commands
|
|
|
|
|
2013-06-22 00:17:52 +04:00
|
|
|
import (
|
2013-06-22 04:01:00 +04:00
|
|
|
"fmt"
|
2013-06-22 00:17:52 +04:00
|
|
|
"github.com/jingweno/gh/git"
|
2013-06-22 04:01:00 +04:00
|
|
|
"github.com/jingweno/gh/github"
|
2013-06-22 00:17:52 +04:00
|
|
|
"github.com/jingweno/gh/utils"
|
2013-06-22 04:01:00 +04:00
|
|
|
"regexp"
|
2013-06-22 00:17:52 +04:00
|
|
|
)
|
|
|
|
|
2013-06-21 22:40:42 +04:00
|
|
|
var cmdCheckout = &Command{
|
|
|
|
Run: checkout,
|
|
|
|
GitExtension: true,
|
|
|
|
Usage: "checkout PULLREQ-URL [BRANCH]",
|
|
|
|
Short: "Switch the active branch to another branch",
|
|
|
|
}
|
|
|
|
|
2013-06-22 00:17:52 +04:00
|
|
|
/**
|
|
|
|
$ 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
|
|
|
|
**/
|
2013-06-26 19:48:34 +04:00
|
|
|
func checkout(command *Command, args *Args) {
|
2013-06-22 04:01:00 +04:00
|
|
|
var err error
|
2013-06-26 19:48:34 +04:00
|
|
|
if !args.IsEmpty() {
|
|
|
|
err = transformCheckoutArgs(args)
|
2013-06-22 05:02:29 +04:00
|
|
|
utils.Fatal(err)
|
2013-06-22 00:17:52 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-26 19:48:34 +04:00
|
|
|
func transformCheckoutArgs(args *Args) error {
|
|
|
|
id := parsePullRequestId(args.First())
|
2013-06-22 04:01:00 +04:00
|
|
|
if id != "" {
|
2013-06-26 19:48:34 +04:00
|
|
|
url := args.Remove(0)
|
2013-06-22 04:01:00 +04:00
|
|
|
gh := github.New()
|
|
|
|
pullRequest, err := gh.PullRequest(id)
|
|
|
|
if err != nil {
|
2013-06-26 19:48:34 +04:00
|
|
|
return err
|
2013-06-22 04:01:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
user := pullRequest.User.Login
|
|
|
|
branch := pullRequest.Head.Ref
|
|
|
|
if pullRequest.Head.Repo.ID == 0 {
|
2013-06-26 19:48:34 +04:00
|
|
|
return fmt.Errorf("%s's fork is not available anymore", user)
|
2013-06-22 04:01:00 +04:00
|
|
|
}
|
2013-06-22 05:02:29 +04:00
|
|
|
|
2013-06-25 01:11:40 +04:00
|
|
|
remoteExists, err := checkIfRemoteExists(user)
|
2013-06-22 17:24:07 +04:00
|
|
|
if err != nil {
|
2013-06-26 19:48:34 +04:00
|
|
|
return err
|
2013-06-22 17:24:07 +04:00
|
|
|
}
|
|
|
|
|
2013-06-25 00:43:59 +04:00
|
|
|
if remoteExists {
|
2013-06-29 01:21:48 +04:00
|
|
|
updateExistingRemote(args, user, branch)
|
2013-06-22 05:02:29 +04:00
|
|
|
} else {
|
2013-06-29 01:21:48 +04:00
|
|
|
err = addRmote(args, user, branch, url, pullRequest.Head.Repo.Private)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2013-06-22 05:02:29 +04:00
|
|
|
}
|
2013-06-22 04:01:00 +04:00
|
|
|
|
|
|
|
var newBranchName string
|
2013-06-26 19:48:34 +04:00
|
|
|
if args.Size() > 0 {
|
|
|
|
newBranchName = args.Remove(0)
|
2013-06-22 04:01:00 +04:00
|
|
|
} else {
|
|
|
|
newBranchName = fmt.Sprintf("%s-%s", user, branch)
|
|
|
|
}
|
2013-06-25 01:11:40 +04:00
|
|
|
trackedBranch := fmt.Sprintf("%s/%s", user, branch)
|
2013-06-22 04:01:00 +04:00
|
|
|
|
2013-06-26 19:48:34 +04:00
|
|
|
args.Append("--track", "-B", newBranchName, trackedBranch)
|
2013-06-22 04:01:00 +04:00
|
|
|
|
2013-06-26 19:48:34 +04:00
|
|
|
return nil
|
2013-06-22 04:01:00 +04:00
|
|
|
}
|
|
|
|
|
2013-06-26 19:48:34 +04:00
|
|
|
return nil
|
2013-06-22 04:01:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func parsePullRequestId(url string) string {
|
|
|
|
pullURLRegex := regexp.MustCompile("https://github\\.com/.+/.+/pull/(\\d+)")
|
|
|
|
if pullURLRegex.MatchString(url) {
|
|
|
|
return pullURLRegex.FindStringSubmatch(url)[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
return ""
|
2013-06-21 22:40:42 +04:00
|
|
|
}
|
2013-06-25 01:11:40 +04:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2013-06-29 01:21:48 +04:00
|
|
|
func updateExistingRemote(args *Args, user, branch string) {
|
|
|
|
args.Before("git", "remote", "set-branches", "--add", user, branch)
|
2013-06-25 01:11:40 +04:00
|
|
|
remoteURL := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branch, user, branch)
|
2013-06-29 01:21:48 +04:00
|
|
|
args.Before("git", "fetch", user, remoteURL)
|
2013-06-25 01:11:40 +04:00
|
|
|
}
|
|
|
|
|
2013-06-29 01:21:48 +04:00
|
|
|
func addRmote(args *Args, user, branch, url string, isPrivate bool) error {
|
2013-06-25 01:11:40 +04:00
|
|
|
project, err := github.ParseProjectFromURL(url)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
sshURL := project.GitURL("", user, isPrivate)
|
2013-06-29 01:21:48 +04:00
|
|
|
args.Before("git", "remote", "add", "-f", "-t", branch, user, sshURL)
|
2013-06-25 01:11:40 +04:00
|
|
|
|
2013-06-29 01:21:48 +04:00
|
|
|
return nil
|
2013-06-25 01:11:40 +04:00
|
|
|
}
|