This repository has been archived by the owner on Jun 17, 2021. It is now read-only.
forked from mislav/hub
-
Notifications
You must be signed in to change notification settings - Fork 0
/
checkout.go
129 lines (105 loc) · 3.13 KB
/
checkout.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
126
127
128
129
package commands
import (
"fmt"
"regexp"
"github.com/github/hub/github"
"github.com/github/hub/utils"
)
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.
`,
}
func init() {
CmdRunner.Use(cmdCheckout)
}
/**
$ hub checkout https://github.com/jingweno/gh/pull/73
> git remote add -f --no-tags -t feature git://github:com/foo/gh.git
> git checkout --track -B foo-feature foo/feature
$ hub checkout https://github.com/jingweno/gh/pull/73 custom-branch-name
**/
func checkout(command *Command, args *Args) {
if !args.IsParamsEmpty() {
err := transformCheckoutArgs(args)
utils.Check(err)
}
}
func transformCheckoutArgs(args *Args) error {
words := args.Words()
if len(words) == 0 {
return nil
}
checkoutURL := words[0]
var newBranchName string
if len(words) > 1 {
newBranchName = words[1]
}
url, err := github.ParseURL(checkoutURL)
if err != nil {
// not a valid GitHub URL
return nil
}
pullURLRegex := regexp.MustCompile("^pull/(\\d+)")
projectPath := url.ProjectPath()
if !pullURLRegex.MatchString(projectPath) {
// not a valid PR URL
return nil
}
err = sanitizeCheckoutFlags(args)
if err != nil {
return err
}
id := pullURLRegex.FindStringSubmatch(projectPath)[1]
gh := github.NewClient(url.Project.Host)
pullRequest, err := gh.PullRequest(url.Project, id)
if err != nil {
return err
}
if idx := args.IndexOfParam(newBranchName); idx >= 0 {
args.RemoveParam(idx)
}
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
if newBranchName == "" {
newBranchName = fmt.Sprintf("%s-%s", user, branch)
}
repo, err := github.LocalRepo()
utils.Check(err)
_, err = repo.RemoteByName(user)
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(headRepo.Name, user, headRepo.Private)
args.Before("git", "remote", "add", "-f", "--no-tags", "-t", branch, user, u)
}
remoteName := fmt.Sprintf("%s/%s", user, branch)
replaceCheckoutParam(args, checkoutURL, newBranchName, remoteName)
return nil
}
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)
}