Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new subcommand git pull-request info #1109

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ type Command struct {
Long string
GitExtension bool

// IgnoreUnknownSubcommands defines whether this command accepts both
// subcommands and non-flag parameters. If that's the case unknown
// subcommands will be handled as the first parameter.
IgnoreUnknownSubcommands bool

subCommands map[string]*Command
}

Expand Down Expand Up @@ -128,6 +133,8 @@ func (c *Command) lookupSubCommand(args *Args) (runCommand *Command, err error)
if subCommand, ok := c.subCommands[subCommandName]; ok {
runCommand = subCommand
args.Params = args.Params[1:]
} else if c.IgnoreUnknownSubcommands {
runCommand = c
} else {
err = fmt.Errorf("error: Unknown subcommand: %s", subCommandName)
}
Expand Down
119 changes: 113 additions & 6 deletions commands/pull_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,30 @@ import (

"github.com/github/hub/git"
"github.com/github/hub/github"
"github.com/github/hub/ui"
"github.com/github/hub/utils"
"github.com/octokit/go-octokit/octokit"
)

var cmdPullRequest = &Command{
Run: pullRequest,
Usage: `
var (
cmdPullRequest = &Command{
Run: pullRequest,
IgnoreUnknownSubcommands: true,
Usage: `
pull-request [-fo] [-b <BASE>] [-h <HEAD>] [-a <USER>] [-M <MILESTONE>] [-l <LABELS>]
pull-request -m <MESSAGE>
pull-request -F <FILE>
pull-request -i <ISSUE>
pull-request info [-b <BASE>] [-h <HEAD>]
`,
Long: `Create a GitHub pull request.
Long: `Manage GitHub pull requests.

## Commands:

With no subcommand, creates a GitHub pull request.

* _info_:
Show info for the GitHub pull request corresponding to a branch.

## Options:
-f, --force
Expand Down Expand Up @@ -58,7 +69,12 @@ pull-request -i <ISSUE>

hub(1), hub-merge(1), hub-checkout(1)
`,
}
}
cmdPullRequestInfo = &Command{
Key: "info",
Run: pullRequestInfo,
}
)

var (
flagPullRequestBase,
Expand All @@ -67,7 +83,9 @@ var (
flagPullRequestMessage,
flagPullRequestAssignee,
flagPullRequestLabels,
flagPullRequestFile string
flagPullRequestFile,
flagPullRequestInfoBase,
flagPullRequestInfoHead string
flagPullRequestBrowse,
flagPullRequestForce bool
flagPullRequestMilestone uint64
Expand All @@ -85,6 +103,11 @@ func init() {
cmdPullRequest.Flag.Uint64VarP(&flagPullRequestMilestone, "milestone", "M", 0, "MILESTONE")
cmdPullRequest.Flag.StringVarP(&flagPullRequestLabels, "labels", "l", "", "LABELS")

cmdPullRequestInfo.Flag.StringVarP(&flagPullRequestInfoBase, "base", "b", "", "BASE")
cmdPullRequestInfo.Flag.StringVarP(&flagPullRequestInfoHead, "head", "h", "", "HEAD")

cmdPullRequest.Use(cmdPullRequestInfo)

CmdRunner.Use(cmdPullRequest)
}

Expand Down Expand Up @@ -314,3 +337,87 @@ func parsePullRequestIssueNumber(url string) string {

return ""
}

// pullRequestInfo fetches info for a pull request.
func pullRequestInfo(cmd *Command, args *Args) {
localRepo, err := github.LocalRepo()
utils.Check(err)

currentBranch, err := localRepo.CurrentBranch()
utils.Check(err)

baseProject, err := localRepo.MainProject()
utils.Check(err)

host, err := github.CurrentConfig().PromptForHost(baseProject.Host)
if err != nil {
utils.Check(github.FormatError("getting pull request info", err))
}

trackedBranch, headProject, err := localRepo.RemoteBranchAndProject(host.User, false)

var (
base, head string
)

if flagPullRequestInfoBase != "" {
baseProject, base = parsePullRequestProject(baseProject, flagPullRequestInfoBase)
}

if flagPullRequestInfoHead != "" {
headProject, head = parsePullRequestProject(headProject, flagPullRequestInfoHead)
}

if base == "" {
masterBranch := localRepo.MasterBranch()
base = masterBranch.ShortName()
}

if head == "" && trackedBranch != nil {
if !trackedBranch.IsRemote() {
// the current branch tracking another branch
// pretend there's no upstream at all
trackedBranch = nil
} else {
if baseProject.SameAs(headProject) && base == trackedBranch.ShortName() {
e := fmt.Errorf(`Aborted: head branch is the same as base ("%s")`, base)
e = fmt.Errorf("%s\n(use `-h <branch>` to specify an explicit pull request head)", e)
utils.Check(e)
}
}
}

if head == "" {
if trackedBranch == nil {
head = currentBranch.ShortName()
} else {
head = trackedBranch.ShortName()
}
}

fullHead := fmt.Sprintf("%s:%s", headProject.Owner, head)

client := github.NewClientWithHost(host)
pr, err := client.FindPullRequest(baseProject, base, fullHead)
utils.Check(err)

comments, err := client.PullRequestComments(pr)
utils.Check(err)

ui.Printf("Title: %q\n", trimToOneLine(pr.Title))
for _, comment := range comments {
ui.Printf("* %s - %s: %s\n", comment.UpdatedAt.Format("2006-01-02 15:04:05"), comment.User.Login, trimToOneLine(comment.Body))
}

args.Replace("echo", "", "URL:", pr.HTMLURL)
}

func trimToOneLine(s string) string {
if i := strings.IndexAny(s, "\r\n"); i != -1 {
s = s[:i] + "…"
}
if len(s) >= 80 {
s = s[:80] + "…"
}
return s
}
18 changes: 18 additions & 0 deletions commands/pull_request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,21 @@ func TestPullRequest_ParsePullRequestProject(t *testing.T) {
assert.Equal(t, "mojombo", p.Owner)
assert.Equal(t, "jekyll", p.Name)
}

func TestPullRequest_TrimToOneLine(t *testing.T) {
tests := []struct {
input string
expected string
}{
{"A short string.", "A short string."},
{"On two\nlines.", "On two…"},
{"With a double\r\nline break.", "With a double…"},
{"A veeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrryyyy looooooooooooong line that is too big to fit.", "A veeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrryyyy looooooooooooong line …"},
}

for _, test := range tests {
if got := trimToOneLine(test.input); got != test.expected {
t.Errorf("trimToOneLine(%q) = %q, want %q", test.input, got, test.expected)
}
}
}
157 changes: 157 additions & 0 deletions features/pull_request_info.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
Feature: hub pull-request info
Background:
Given I am in "git://github.com/github/hub.git" git repo
And I am "cornwe19" on github.com with OAuth token "OTOKEN"

Scenario: Basic pull request
Given I am on the "master" branch pushed to "origin/master"
When I successfully run `git checkout --quiet -b topic`
Given I make a commit with message "ăéñøü"
And the "topic" branch is pushed to "origin/topic"
And the GitHub API server:
"""
get('/repos/github/hub/pulls') {
assert :base => "master",
:head => "github:topic"
json([
{ :title => "Description of my own pull request",
:comments_url => "https://api.github.com/repos/github/hub/issues/4242/comments",
:html_url => "https://github.com/github/hub/pull/4242"
}
])
}
get('/repos/github/hub/issues/4242/comments') {
json([
{ :user => {
:login => "pcorpet"
},
:body => "A nice comment.",
:created_at => "2016-02-11T11:02:50Z",
:updated_at => "2016-02-11T15:27:33Z"
},
{ :user => {
:login => "lascap"
},
:body => "A second comment.",
:created_at => "2016-02-11T11:02:54Z",
:updated_at => "2016-02-11T11:02:54Z",
}
])
}
"""
When I run `hub pull-request info`
Then the output should contain exactly:
"""
Title: "Description of my own pull request"
* 2016-02-11 15:27:33 - pcorpet: A nice comment.
* 2016-02-11 11:02:54 - lascap: A second comment.
URL: https://github.com/github/hub/pull/4242

"""

Scenario: No pull request for the branch yet
Given I am on the "master" branch pushed to "origin/master"
When I successfully run `git checkout --quiet -b topic`
Given I make a commit with message "ăéñøü"
And the "topic" branch is pushed to "origin/topic"
And the GitHub API server:
"""
get('/repos/github/hub/pulls') {
assert :base => "master",
:head => "github:topic"
json([])
}
"""
When I run `hub pull-request info`
Then the output should contain exactly "no such pull request\n"

Scenario: Very long lines
Given I am on the "master" branch pushed to "origin/master"
When I successfully run `git checkout --quiet -b topic`
Given I make a commit with message "ăéñøü"
And the "topic" branch is pushed to "origin/topic"
And the GitHub API server:
"""
get('/repos/github/hub/pulls') {
assert :base => "master",
:head => "github:topic"
json([
{ :title => "Very long description that could go on and on for hours, but I am just too lazy to make it even bigger. You got the spirit I think.",
:comments_url => "https://api.github.com/repos/github/hub/issues/4242/comments",
:html_url => "https://github.com/github/hub/pull/4242"
}
])
}
get('/repos/github/hub/issues/4242/comments') {
json([
{ :user => {
:login => "pcorpet"
},
:body => "A very nice comment that is so long that it wouldn't fit on one line in a terminal, even with a very very large terminal I really doubt that it would fit entirely. Except if you had reduced the font on purpose.",
:created_at => "2016-02-11T11:02:50Z",
:updated_at => "2016-02-11T15:27:33Z"
},
{ :user => {
:login => "lascap"
},
:body => "A second comment. This one is also very long, but don't let that stop you. I could have written some very understanding towards the end of the line. Or not.",
:created_at => "2016-02-11T11:02:54Z",
:updated_at => "2016-02-11T11:02:54Z",
}
])
}
"""
When I run `hub pull-request info`
Then the output should contain exactly:
"""
Title: "Very long description that could go on and on for hours, but I am just too lazy …"
* 2016-02-11 15:27:33 - pcorpet: A very nice comment that is so long that it wouldn't fit on one line in a termin…
* 2016-02-11 11:02:54 - lascap: A second comment. This one is also very long, but don't let that stop you. I cou…
URL: https://github.com/github/hub/pull/4242

"""

Scenario: Text on several lines
Given I am on the "master" branch pushed to "origin/master"
When I successfully run `git checkout --quiet -b topic`
Given I make a commit with message "ăéñøü"
And the "topic" branch is pushed to "origin/topic"
And the GitHub API server:
"""
get('/repos/github/hub/pulls') {
assert :base => "master",
:head => "github:topic"
json([
{ :title => "A title is always on one line only.",
:comments_url => "https://api.github.com/repos/github/hub/issues/4242/comments",
:html_url => "https://github.com/github/hub/pull/4242"
}
])
}
get('/repos/github/hub/issues/4242/comments') {
json([
{ :user => {
:login => "pcorpet"
},
:body => "A comment\nthat is on 2 lines.",
:updated_at => "2016-02-11T15:27:33Z"
},
{ :user => {
:login => "lascap"
},
:body => "Another comment.\nAlso on 2 lines.",
:created_at => "2016-02-11T11:02:54Z",
:updated_at => "2016-02-11T11:02:54Z",
}
])
}
"""
When I run `hub pull-request info`
Then the output should contain exactly:
"""
Title: "A title is always on one line only."
* 2016-02-11 15:27:33 - pcorpet: A comment…
* 2016-02-11 11:02:54 - lascap: Another comment.…
URL: https://github.com/github/hub/pull/4242

"""
Loading