Skip to content

Commit 252e29e

Browse files
authored
Merge pull request cli#17 from github/ghr-context
add context package
2 parents 9704bb5 + d334d56 commit 252e29e

27 files changed

+630
-2094
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,8 @@ BUILD_FILES = $(shell go list -f '{{range .GoFiles}}{{$$.Dir}}/{{.}}\
55

66
bin/gh: $(BUILD_FILES)
77
go build -o "$@"
8+
9+
test:
10+
go test ./...
11+
12+
.PHONY: test

api/client.go

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ import (
77
"io/ioutil"
88
"net/http"
99
"os"
10-
"os/user"
11-
"regexp"
1210

11+
"github.com/github/gh-cli/context"
1312
"github.com/github/gh-cli/version"
1413
)
1514

@@ -57,7 +56,7 @@ var GraphQL = func(query string, variables map[string]string, data interface{})
5756
return err
5857
}
5958

60-
token, err := getToken()
59+
token, err := context.Current().AuthToken()
6160
if err != nil {
6261
return err
6362
}
@@ -138,20 +137,3 @@ func debugResponse(resp *http.Response, body string) {
138137

139138
fmt.Printf("DEBUG: GraphQL response:\n%+v\n\n%s\n\n", resp, body)
140139
}
141-
142-
// TODO: Everything below this line will be removed when Nate's context work is complete
143-
func getToken() (string, error) {
144-
usr, err := user.Current()
145-
if err != nil {
146-
return "", err
147-
}
148-
149-
content, err := ioutil.ReadFile(usr.HomeDir + "/.config/hub")
150-
if err != nil {
151-
return "", err
152-
}
153-
154-
r := regexp.MustCompile(`oauth_token: (\w+)`)
155-
token := r.FindStringSubmatch(string(content))
156-
return token[1], nil
157-
}

api/queries.go

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package api
22

33
import (
44
"fmt"
5-
"strings"
65

7-
"github.com/github/gh-cli/git"
8-
"github.com/github/gh-cli/github"
6+
"github.com/github/gh-cli/context"
97
)
108

119
type PullRequestsPayload struct {
@@ -21,7 +19,7 @@ type PullRequest struct {
2119
HeadRefName string
2220
}
2321

24-
func PullRequests() (PullRequestsPayload, error) {
22+
func PullRequests() (*PullRequestsPayload, error) {
2523
type edges struct {
2624
Edges []struct {
2725
Node PullRequest
@@ -81,13 +79,24 @@ func PullRequests() (PullRequestsPayload, error) {
8179
}
8280
`
8381

84-
project := project()
85-
owner := project.Owner
86-
repo := project.Name
87-
currentBranch := currentBranch()
82+
ghRepo, err := context.Current().BaseRepo()
83+
if err != nil {
84+
return nil, err
85+
}
86+
currentBranch, err := context.Current().Branch()
87+
if err != nil {
88+
return nil, err
89+
}
90+
currentUsername, err := context.Current().AuthLogin()
91+
if err != nil {
92+
return nil, err
93+
}
8894

89-
viewerQuery := fmt.Sprintf("repo:%s/%s state:open is:pr author:%s", owner, repo, currentUsername())
90-
reviewerQuery := fmt.Sprintf("repo:%s/%s state:open review-requested:%s", owner, repo, currentUsername())
95+
owner := ghRepo.Owner
96+
repo := ghRepo.Name
97+
98+
viewerQuery := fmt.Sprintf("repo:%s/%s state:open is:pr author:%s", owner, repo, currentUsername)
99+
reviewerQuery := fmt.Sprintf("repo:%s/%s state:open review-requested:%s", owner, repo, currentUsername)
91100

92101
variables := map[string]string{
93102
"viewerQuery": viewerQuery,
@@ -98,9 +107,9 @@ func PullRequests() (PullRequestsPayload, error) {
98107
}
99108

100109
var resp response
101-
err := GraphQL(query, variables, &resp)
110+
err = GraphQL(query, variables, &resp)
102111
if err != nil {
103-
return PullRequestsPayload{}, err
112+
return nil, err
104113
}
105114

106115
var viewerCreated []PullRequest
@@ -124,37 +133,5 @@ func PullRequests() (PullRequestsPayload, error) {
124133
currentPR,
125134
}
126135

127-
return payload, nil
128-
}
129-
130-
// TODO: Everything below this line will be removed when Nate's context work is complete
131-
func project() github.Project {
132-
remotes, error := github.Remotes()
133-
if error != nil {
134-
panic(error)
135-
}
136-
for _, remote := range remotes {
137-
if project, error := remote.Project(); error == nil {
138-
return *project
139-
}
140-
}
141-
142-
panic("Could not get the project. What is a project? I don't know, it's kind of like a git repository I think?")
143-
}
144-
145-
func currentBranch() string {
146-
currentBranch, err := git.Head()
147-
if err != nil {
148-
panic(err)
149-
}
150-
151-
return strings.Replace(currentBranch, "refs/heads/", "", 1)
152-
}
153-
154-
func currentUsername() string {
155-
host, err := github.CurrentConfig().DefaultHost()
156-
if err != nil {
157-
panic(err)
158-
}
159-
return host.User
136+
return &payload, nil
160137
}

command/pr.go

Lines changed: 16 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@ package command
22

33
import (
44
"fmt"
5-
"net/url"
6-
"os"
75
"os/exec"
86
"strconv"
9-
"strings"
107

118
"github.com/github/gh-cli/api"
12-
"github.com/github/gh-cli/git"
13-
"github.com/github/gh-cli/github"
9+
"github.com/github/gh-cli/context"
1410
"github.com/github/gh-cli/utils"
1511
"github.com/spf13/cobra"
1612
)
@@ -52,7 +48,11 @@ func prList(cmd *cobra.Command, args []string) error {
5248
if prPayload.CurrentPR != nil {
5349
printPrs(*prPayload.CurrentPR)
5450
} else {
55-
message := fmt.Sprintf(" There is no pull request associated with %s", utils.Cyan("["+currentBranch()+"]"))
51+
currentBranch, err := context.Current().Branch()
52+
if err != nil {
53+
return err
54+
}
55+
message := fmt.Sprintf(" There is no pull request associated with %s", utils.Cyan("["+currentBranch+"]"))
5656
printMessage(message)
5757
}
5858
fmt.Println()
@@ -77,19 +77,26 @@ func prList(cmd *cobra.Command, args []string) error {
7777
}
7878

7979
func prView(cmd *cobra.Command, args []string) error {
80-
project := project()
80+
baseRepo, err := context.Current().BaseRepo()
81+
if err != nil {
82+
return err
83+
}
8184

8285
var openURL string
8386
if len(args) > 0 {
8487
if prNumber, err := strconv.Atoi(args[0]); err == nil {
85-
openURL = project.WebURL("", "", fmt.Sprintf("pull/%d", prNumber))
88+
// TODO: move URL generation into GitHubRepository
89+
openURL = fmt.Sprintf("https://github.com/%s/%s/pull/%d", baseRepo.Owner, baseRepo.Name, prNumber)
8690
} else {
8791
return fmt.Errorf("invalid pull request number: '%s'", args[0])
8892
}
8993
} else {
9094
prPayload, err := api.PullRequests()
9195
if err != nil || prPayload.CurrentPR == nil {
92-
branch := currentBranch()
96+
branch, err := context.Current().Branch()
97+
if err != nil {
98+
return err
99+
}
93100
return fmt.Errorf("The [%s] branch has no open PRs", branch)
94101
}
95102
openURL = prPayload.CurrentPR.URL
@@ -130,41 +137,3 @@ func openInBrowser(url string) error {
130137
endingArgs := append(launcher[1:], url)
131138
return exec.Command(launcher[0], endingArgs...).Run()
132139
}
133-
134-
// The functions below should be replaced at some point by the context package
135-
// 🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨🧨
136-
func currentBranch() string {
137-
currentBranch, err := git.Head()
138-
if err != nil {
139-
panic(err)
140-
}
141-
142-
return strings.Replace(currentBranch, "refs/heads/", "", 1)
143-
}
144-
145-
func project() github.Project {
146-
if repoFromEnv := os.Getenv("GH_REPO"); repoFromEnv != "" {
147-
repoURL, err := url.Parse(fmt.Sprintf("https://github.com/%s.git", repoFromEnv))
148-
if err != nil {
149-
panic(err)
150-
}
151-
project, err := github.NewProjectFromURL(repoURL)
152-
if err != nil {
153-
panic(err)
154-
}
155-
return *project
156-
}
157-
158-
remotes, err := github.Remotes()
159-
if err != nil {
160-
panic(err)
161-
}
162-
163-
for _, remote := range remotes {
164-
if project, err := remote.Project(); err == nil {
165-
return *project
166-
}
167-
}
168-
169-
panic("Could not get the project. What is a project? I don't know, it's kind of like a git repository I think?")
170-
}

command/pr_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import (
44
"regexp"
55
"testing"
66

7+
"github.com/github/gh-cli/context"
78
"github.com/github/gh-cli/test"
89
)
910

1011
func TestPRList(t *testing.T) {
12+
ctx := context.InitBlankContext()
13+
ctx.SetBaseRepo("github/FAKE-GITHUB-REPO-NAME")
14+
ctx.SetBranch("master")
15+
1116
teardown := test.MockGraphQLResponse("test/fixtures/pr.json")
1217
defer teardown()
1318

14-
gitRepo := test.UseTempGitRepo()
15-
defer gitRepo.TearDown()
16-
1719
output, err := test.RunCommand(RootCmd, "pr list")
1820
if err != nil {
1921
t.Errorf("error running command `pr list`: %v", err)

command/root.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,34 @@ package command
22

33
import (
44
"fmt"
5+
"os"
56

7+
"github.com/github/gh-cli/context"
8+
"github.com/github/gh-cli/git"
69
"github.com/spf13/cobra"
710
)
811

12+
var (
13+
currentRepo string
14+
currentBranch string
15+
)
16+
17+
func init() {
18+
RootCmd.PersistentFlags().StringVarP(&currentRepo, "repo", "R", "", "current GitHub repository")
19+
RootCmd.PersistentFlags().StringVarP(&currentBranch, "current-branch", "B", "", "current git branch")
20+
21+
ctx := context.InitDefaultContext()
22+
ctx.SetBranch(currentBranch)
23+
repo := currentRepo
24+
if repo == "" {
25+
repo = os.Getenv("GH_REPO")
26+
}
27+
ctx.SetBaseRepo(repo)
28+
29+
git.InitSSHAliasMap(nil)
30+
}
31+
32+
// RootCmd is the entry point of command-line execution
933
var RootCmd = &cobra.Command{
1034
Use: "gh",
1135
Short: "GitHub CLI",

context/blank_context.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package context
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
// InitBlankContext initializes a blank context for testing
9+
func InitBlankContext() Context {
10+
currentContext = &blankContext{
11+
authToken: "OTOKEN",
12+
authLogin: "monalisa",
13+
}
14+
return currentContext
15+
}
16+
17+
// A Context implementation that queries the filesystem
18+
type blankContext struct {
19+
authToken string
20+
authLogin string
21+
branch string
22+
baseRepo *GitHubRepository
23+
}
24+
25+
func (c *blankContext) AuthToken() (string, error) {
26+
return c.authToken, nil
27+
}
28+
29+
func (c *blankContext) AuthLogin() (string, error) {
30+
return c.authLogin, nil
31+
}
32+
33+
func (c *blankContext) Branch() (string, error) {
34+
if c.branch == "" {
35+
return "", fmt.Errorf("branch was not initialized")
36+
}
37+
return c.branch, nil
38+
}
39+
40+
func (c *blankContext) SetBranch(b string) {
41+
c.branch = b
42+
}
43+
44+
func (c *blankContext) Remotes() (Remotes, error) {
45+
return Remotes{}, nil
46+
}
47+
48+
func (c *blankContext) BaseRepo() (*GitHubRepository, error) {
49+
if c.baseRepo == nil {
50+
return nil, fmt.Errorf("base repo was not initialized")
51+
}
52+
return c.baseRepo, nil
53+
}
54+
55+
func (c *blankContext) SetBaseRepo(nwo string) {
56+
parts := strings.SplitN(nwo, "/", 2)
57+
if len(parts) == 2 {
58+
c.baseRepo = &GitHubRepository{
59+
Owner: parts[0],
60+
Name: parts[1],
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)