hub/commands/checkout.go

130 строки
3.2 KiB
Go
Исходник Обычный вид История

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"
2014-04-01 00:01:05 +04:00
"regexp"
2014-02-10 20:22:36 +04:00
"github.com/github/hub/github"
"github.com/github/hub/utils"
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",
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.
`,
2013-06-21 22:40:42 +04:00
}
func init() {
CmdRunner.Use(cmdCheckout)
}
2013-06-22 00:17:52 +04:00
/**
2016-01-19 21:31:47 +03:00
$ hub checkout https://github.com/jingweno/gh/pull/73
> git remote add -f --no-tags -t feature git://github:com/foo/gh.git
2013-06-30 20:00:21 +04:00
> git checkout --track -B foo-feature foo/feature
2013-06-22 00:17:52 +04:00
2016-01-19 21:31:47 +03:00
$ hub checkout https://github.com/jingweno/gh/pull/73 custom-branch-name
2013-06-22 00:17:52 +04:00
**/
2013-06-26 19:48:34 +04:00
func checkout(command *Command, args *Args) {
2013-07-02 22:56:45 +04:00
if !args.IsParamsEmpty() {
2013-07-02 22:28:50 +04:00
err := transformCheckoutArgs(args)
2013-07-05 03:18:28 +04:00
utils.Check(err)
2013-06-22 00:17:52 +04:00
}
}
2013-06-26 19:48:34 +04:00
func transformCheckoutArgs(args *Args) error {
2013-12-11 10:05:26 +04:00
words := args.Words()
2014-04-01 00:01:05 +04:00
2013-12-11 10:05:26 +04:00
if len(words) == 0 {
return nil
}
2013-06-22 04:01:00 +04:00
2013-12-11 10:05:26 +04:00
checkoutURL := words[0]
var newBranchName string
if len(words) > 1 {
newBranchName = words[1]
}
2014-04-01 00:01:05 +04:00
url, err := github.ParseURL(checkoutURL)
if err != nil {
// not a valid GitHub URL
return nil
}
2013-06-22 05:02:29 +04:00
2013-12-11 10:05:26 +04:00
pullURLRegex := regexp.MustCompile("^pull/(\\d+)")
projectPath := url.ProjectPath()
if !pullURLRegex.MatchString(projectPath) {
2014-04-01 00:01:05 +04:00
// not a valid PR URL
2013-12-11 10:05:26 +04:00
return nil
}
2013-07-02 22:28:50 +04:00
err = sanitizeCheckoutFlags(args)
if err != nil {
return err
}
2013-12-11 10:05:26 +04:00
id := pullURLRegex.FindStringSubmatch(projectPath)[1]
2013-12-17 19:45:48 +04:00
gh := github.NewClient(url.Project.Host)
pullRequest, err := gh.PullRequest(url.Project, id)
2013-12-11 10:05:26 +04:00
if err != nil {
return err
}
2013-06-22 04:01:00 +04:00
2013-12-11 10:05:26 +04:00
if idx := args.IndexOfParam(newBranchName); idx >= 0 {
args.RemoveParam(idx)
}
2013-06-22 04:01:00 +04:00
branch := pullRequest.Head.Ref
headRepo := pullRequest.Head.Repo
if headRepo == nil {
return fmt.Errorf("Error: that fork is not available anymore")
}
user := headRepo.Owner.Login
2013-12-11 10:05:26 +04:00
if newBranchName == "" {
newBranchName = fmt.Sprintf("%s-%s", user, branch)
2013-06-22 04:01:00 +04:00
}
repo, err := github.LocalRepo()
utils.Check(err)
_, err = repo.RemoteByName(user)
2013-12-11 10:05:26 +04:00
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 {
u := url.Project.GitURL(pullRequest.Head.Repo.Name, user, pullRequest.Head.Repo.Private)
args.Before("git", "remote", "add", "-f", "--no-tags", "-t", branch, user, u)
2013-12-11 10:05:26 +04:00
}
2013-06-22 04:01:00 +04:00
remoteName := fmt.Sprintf("%s/%s", user, branch)
replaceCheckoutParam(args, checkoutURL, newBranchName, remoteName)
2013-06-25 01:11:40 +04:00
2013-12-11 10:05:26 +04:00
return nil
2013-07-02 22:28:50 +04:00
}
func sanitizeCheckoutFlags(args *Args) error {
if i := args.IndexOfParam("-b"); i != -1 {
return fmt.Errorf("Unsupported flag -b when checking out pull request")
}
if i := args.IndexOfParam("--orphan"); i != -1 {
return fmt.Errorf("Unsupported flag --orphan when checking out pull request")
}
return nil
}
func replaceCheckoutParam(args *Args, checkoutURL, branchName, remoteName string) {
idx := args.IndexOfParam(checkoutURL)
args.RemoveParam(idx)
args.InsertParam(idx, "--track", "-B", branchName, remoteName)
}