github.com/pengwynn/gh@v1.0.1-0.20140118055701-14327ca3942e/commands/checkout.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/jingweno/gh/github"
     6  	"github.com/jingweno/gh/utils"
     7  	"regexp"
     8  )
     9  
    10  var cmdCheckout = &Command{
    11  	Run:          checkout,
    12  	GitExtension: true,
    13  	Usage:        "checkout PULLREQ-URL [BRANCH]",
    14  	Short:        "Switch the active branch to another branch",
    15  	Long: `Checks out the head of the pull request as a local branch, to allow for
    16  reviewing, rebasing and otherwise cleaning up the commits in the pull
    17  request before merging. The name of the local branch can explicitly be
    18  set with BRANCH.
    19  `,
    20  }
    21  
    22  func init() {
    23  	CmdRunner.Use(cmdCheckout)
    24  }
    25  
    26  /**
    27    $ gh checkout https://github.com/jingweno/gh/pull/73
    28    > git remote add -f -t feature git://github:com/foo/gh.git
    29    > git checkout --track -B foo-feature foo/feature
    30  
    31    $ gh checkout https://github.com/jingweno/gh/pull/73 custom-branch-name
    32  **/
    33  func checkout(command *Command, args *Args) {
    34  	if !args.IsParamsEmpty() {
    35  		err := transformCheckoutArgs(args)
    36  		utils.Check(err)
    37  	}
    38  }
    39  
    40  func transformCheckoutArgs(args *Args) error {
    41  	words := args.Words()
    42  	if len(words) == 0 {
    43  		return nil
    44  	}
    45  
    46  	checkoutURL := words[0]
    47  	url, err := github.ParseURL(checkoutURL)
    48  	if err != nil {
    49  		return nil
    50  	}
    51  	var newBranchName string
    52  	if len(words) > 1 {
    53  		newBranchName = words[1]
    54  	}
    55  
    56  	pullURLRegex := regexp.MustCompile("^pull/(\\d+)")
    57  	projectPath := url.ProjectPath()
    58  	if !pullURLRegex.MatchString(projectPath) {
    59  		return nil
    60  	}
    61  
    62  	id := pullURLRegex.FindStringSubmatch(projectPath)[1]
    63  	gh := github.NewClient(url.Project.Host)
    64  	pullRequest, err := gh.PullRequest(url.Project, id)
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	if idx := args.IndexOfParam(newBranchName); idx >= 0 {
    70  		args.RemoveParam(idx)
    71  	}
    72  
    73  	user, branch := parseUserBranchFromPR(pullRequest)
    74  	if pullRequest.Head.Repo.ID == 0 {
    75  		return fmt.Errorf("Error: %s's fork is not available anymore", user)
    76  	}
    77  
    78  	if newBranchName == "" {
    79  		newBranchName = fmt.Sprintf("%s-%s", user, branch)
    80  	}
    81  
    82  	repo := github.LocalRepo()
    83  	_, err = repo.RemoteByName(user)
    84  	if err == nil {
    85  		args.Before("git", "remote", "set-branches", "--add", user, branch)
    86  		remoteURL := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branch, user, branch)
    87  		args.Before("git", "fetch", user, remoteURL)
    88  	} else {
    89  		u := url.Project.GitURL("", user, pullRequest.Head.Repo.Private)
    90  		args.Before("git", "remote", "add", "-f", "-t", branch, user, u)
    91  	}
    92  
    93  	idx := args.IndexOfParam(checkoutURL)
    94  	args.RemoveParam(idx)
    95  	args.InsertParam(idx, "--track", "-B", newBranchName, fmt.Sprintf("%s/%s", user, branch))
    96  
    97  	return nil
    98  }