未验证 提交 5346928a 编写于 作者: M Mislav Marohnić 提交者: GitHub

Merge pull request #1923 from royels/feature

Add the command `hub issue show <NUMBER>`
......@@ -18,6 +18,7 @@ var (
Run: listIssues,
Usage: `
issue [-a <ASSIGNEE>] [-c <CREATOR>] [-@ <USER>] [-s <STATE>] [-f <FORMAT>] [-M <MILESTONE>] [-l <LABELS>] [-d <DATE>] [-o <SORT_KEY> [-^]] [-L <LIMIT>]
issue show [-f <FORMAT>] <NUMBER>
issue create [-oc] [-m <MESSAGE>|-F <FILE>] [--edit] [-a <USERS>] [-M <MILESTONE>] [-l <LABELS>]
issue labels [--color]
`,
......@@ -27,6 +28,9 @@ issue labels [--color]
With no arguments, show a list of open issues.
* _show_:
Show an existing issue specified by <NUMBER>.
* _create_:
Open an issue in the current project.
......@@ -153,6 +157,13 @@ With no arguments, show a list of open issues.
Long: "Open an issue in the current project.",
}
cmdShowIssue = &Command{
Key: "show",
Run: showIssue,
Usage: "issue show <NUMBER>",
Long: "Show an issue in the current project.",
}
cmdLabel = &Command{
Key: "labels",
Run: listLabels,
......@@ -163,6 +174,7 @@ With no arguments, show a list of open issues.
flagIssueAssignee,
flagIssueState,
flagIssueFormat,
flagShowIssueFormat,
flagIssueMessage,
flagIssueMilestoneFilter,
flagIssueCreator,
......@@ -189,6 +201,8 @@ With no arguments, show a list of open issues.
)
func init() {
cmdShowIssue.Flag.StringVarP(&flagShowIssueFormat, "format", "f", "", "FORMAT")
cmdCreateIssue.Flag.StringVarP(&flagIssueMessage, "message", "m", "", "MESSAGE")
cmdCreateIssue.Flag.StringVarP(&flagIssueFile, "file", "F", "", "FILE")
cmdCreateIssue.Flag.Uint64VarP(&flagIssueMilestone, "milestone", "M", 0, "MILESTONE")
......@@ -213,6 +227,7 @@ func init() {
cmdLabel.Flag.BoolVarP(&flagLabelsColorize, "color", "", false, "COLORIZE")
cmdIssue.Use(cmdShowIssue)
cmdIssue.Use(cmdCreateIssue)
cmdIssue.Use(cmdLabel)
CmdRunner.Use(cmdIssue)
......@@ -381,6 +396,62 @@ func formatIssue(issue github.Issue, format string, colorize bool) string {
return ui.Expand(format, placeholders, colorize)
}
func showIssue(cmd *Command, args *Args) {
issueNumber := cmd.Arg(0)
if issueNumber == "" {
utils.Check(fmt.Errorf(cmd.Synopsis()))
}
localRepo, err := github.LocalRepo()
utils.Check(err)
project, err := localRepo.MainProject()
utils.Check(err)
gh := github.NewClient(project.Host)
var issue = &github.Issue{}
issue, err = gh.FetchIssue(project, issueNumber)
utils.Check(err)
args.NoForward()
colorize := ui.IsTerminal(os.Stdout)
if flagShowIssueFormat != "" {
ui.Printf(formatIssue(*issue, flagShowIssueFormat, colorize))
return
}
var closed = ""
if issue.State != "open" {
closed = "[CLOSED] "
}
commentsList, err := gh.FetchComments(project, issueNumber)
utils.Check(err)
ui.Printf("# %s%s\n\n", closed, issue.Title)
ui.Printf("* created by @%s on %s\n", issue.User.Login, issue.CreatedAt.String())
if len(issue.Assignees) > 0 {
var assignees []string
for _, user := range issue.Assignees {
assignees = append(assignees, user.Login)
}
ui.Printf("* assignees: %s\n", strings.Join(assignees, ", "))
}
ui.Printf("\n%s\n", issue.Body)
if issue.Comments > 0 {
ui.Printf("\n## Comments:\n")
for _, comment := range commentsList {
ui.Printf("\n### comment by @%s on %s\n\n%s\n", comment.User.Login, comment.CreatedAt.String(), comment.Body)
}
}
return
}
func createIssue(cmd *Command, args *Args) {
localRepo, err := github.LocalRepo()
utils.Check(err)
......
......@@ -17,8 +17,8 @@ var (
cmdRelease = &Command{
Run: listReleases,
Usage: `
release [--include-drafts] [--exclude-prereleases] [-L <LIMIT>]
release show <TAG>
release [--include-drafts] [--exclude-prereleases] [-L <LIMIT>] [-f <FORMAT>]
release show [-f <FORMAT>] <TAG>
release create [-dpoc] [-a <FILE>] [-m <MESSAGE>|-F <FILE>] [-t <TARGET>] <TAG>
release edit [<options>] <TAG>
release download <TAG>
......@@ -178,6 +178,7 @@ hub(1), git-tag(1)
flagReleaseMessage,
flagReleaseFile,
flagReleaseFormat,
flagShowReleaseFormat,
flagReleaseCommitish string
flagReleaseAssets stringSliceValue
......@@ -192,6 +193,7 @@ func init() {
cmdRelease.Flag.StringVarP(&flagReleaseFormat, "format", "f", "%T%n", "FORMAT")
cmdShowRelease.Flag.BoolVarP(&flagReleaseShowDownloads, "show-downloads", "d", false, "DRAFTS")
cmdShowRelease.Flag.StringVarP(&flagShowReleaseFormat, "format", "f", "", "FORMAT")
cmdCreateRelease.Flag.BoolVarP(&flagReleaseEdit, "edit", "e", false, "EDIT")
cmdCreateRelease.Flag.BoolVarP(&flagReleaseDraft, "draft", "d", false, "DRAFT")
......@@ -315,6 +317,8 @@ func showRelease(cmd *Command, args *Args) {
gh := github.NewClient(project.Host)
args.NoForward()
if args.Noop {
ui.Printf("Would display information for `%s' release\n", tagName)
} else {
......@@ -323,6 +327,12 @@ func showRelease(cmd *Command, args *Args) {
body := strings.TrimSpace(release.Body)
colorize := ui.IsTerminal(os.Stdout)
if flagShowReleaseFormat != "" {
ui.Printf(formatRelease(*release, flagShowReleaseFormat, colorize))
return
}
ui.Println(release.Name)
if body != "" {
ui.Printf("\n%s\n", body)
......@@ -338,8 +348,6 @@ func showRelease(cmd *Command, args *Args) {
}
}
}
args.NoForward()
}
func downloadRelease(cmd *Command, args *Args) {
......
......@@ -530,3 +530,125 @@ Feature: hub issue
bug
feature\n
"""
Scenario: Fetch single issue
Given the GitHub API server:
"""
get('/repos/github/hub/issues/102') {
json \
:number => 102,
:state => "open",
:body => "I want this feature",
:title => "Feature request for hub issue show",
:created_at => "2017-04-14T16:00:49Z",
:user => { :login => "royels" },
:assignees => [{:login => "royels"}],
:comments => 1
}
get('/repos/github/hub/issues/102/comments') {
json [
{ :body => "I am from the future",
:created_at => "2011-04-14T16:00:49Z",
:user => { :login => "octocat" }
},
{ :body => "I did the thing",
:created_at => "2013-10-30T22:20:00Z",
:user => { :login => "hubot" }
},
]
}
"""
When I successfully run `hub issue show 102`
Then the output should contain exactly:
"""
# Feature request for hub issue show
* created by @royels on 2017-04-14 16:00:49 +0000 UTC
* assignees: royels
I want this feature
## Comments:
### comment by @octocat on 2011-04-14 16:00:49 +0000 UTC
I am from the future
### comment by @hubot on 2013-10-30 22:20:00 +0000 UTC
I did the thing\n
"""
Scenario: Format single issue
Given the GitHub API server:
"""
get('/repos/github/hub/issues/102') {
json \
:number => 102,
:state => "open",
:body => "I want this feature",
:title => "Feature request for hub issue show",
:created_at => "2017-04-14T16:00:49Z",
:user => { :login => "royels" },
:assignees => [{:login => "royels"}],
:comments => 1
}
get('/repos/github/hub/issues/102/comments') {
json [
{ :body => "I am from the future",
:created_at => "2011-04-14T16:00:49Z",
:user => { :login => "octocat" }
},
{ :body => "I did the thing",
:created_at => "2013-10-30T22:20:00Z",
:user => { :login => "hubot" }
},
]
}
"""
When I successfully run `hub issue show 102 --format='%I %t%n%n%b%n'`
Then the output should contain exactly:
"""
102 Feature request for hub issue show
I want this feature\n
"""
Scenario: Did not supply an issue number
When I run `hub issue show`
Then the exit status should be 1
Then the output should contain exactly "Usage: hub issue show <NUMBER>\n"
Scenario: Show error message if http code is not 200 for issues endpoint
Given the GitHub API server:
"""
get('/repos/github/hub/issues/102') {
status 500
}
"""
When I run `hub issue show 102`
Then the output should contain exactly:
"""
Error fetching issue: Internal Server Error (HTTP 500)\n
"""
Scenario: Show error message if http code is not 200 for comments endpoint
Given the GitHub API server:
"""
get('/repos/github/hub/issues/102') {
json \
:number => 102,
:body => "I want this feature",
:title => "Feature request for hub issue show",
:created_at => "2017-04-14T16:00:49Z",
:user => { :login => "royels" }
}
get('/repos/github/hub/issues/102/comments') {
status 404
}
"""
When I run `hub issue show 102`
Then the output should contain exactly:
"""
Error fetching comments for issue: Not Found (HTTP 404)\n
"""
......@@ -325,6 +325,43 @@ MARKDOWN
https://github.com/mislav/will_paginate/archive/v1.2.0.tar.gz\n
"""
Scenario: Format specific release
Given the GitHub API server:
"""
get('/repos/mislav/will_paginate/releases') {
json [
{ tag_name: 'v1.2.0',
name: 'will_paginate 1.2.0',
draft: true,
prerelease: false,
tarball_url: "https://github.com/mislav/will_paginate/archive/v1.2.0.tar.gz",
zipball_url: "https://github.com/mislav/will_paginate/archive/v1.2.0.zip",
assets: [
{ browser_download_url: "https://github.com/mislav/will_paginate/releases/download/v1.2.0/example.zip",
},
],
body: <<MARKDOWN
### Hello to my release
Here is what's broken:
- everything
MARKDOWN
},
]
}
"""
When I successfully run `hub release show v1.2.0 --format='%t (%T)%n%as%n%n%b%n'`
Then the output should contain exactly:
"""
will_paginate 1.2.0 (v1.2.0)
https://github.com/mislav/will_paginate/releases/download/v1.2.0/example.zip
### Hello to my release
Here is what's broken:
- everything\n\n
"""
Scenario: Show release no tag
When I run `hub release show`
Then the exit status should be 1
......
......@@ -525,6 +525,13 @@ func (client *Client) ForkRepository(project *Project, params map[string]interfa
return
}
type Comment struct {
Id int `json:"id"`
Body string `json:"body"`
User *User `json:"user"`
CreatedAt time.Time `json:"created_at"`
}
type Issue struct {
Number int `json:"number"`
State string `json:"state"`
......@@ -550,6 +557,8 @@ type Issue struct {
ApiUrl string `json:"url"`
HtmlUrl string `json:"html_url"`
ClosedBy *User `json:"closed_by"`
}
type PullRequest Issue
......@@ -650,6 +659,38 @@ func (client *Client) FetchIssues(project *Project, filterParams map[string]inte
return
}
func (client *Client) FetchIssue(project *Project, number string) (issue *Issue, err error) {
api, err := client.simpleApi()
if err != nil {
return
}
res, err := api.Get(fmt.Sprintf("repos/%s/%s/issues/%s", project.Owner, project.Name, number))
if err = checkStatus(200, "fetching issue", res, err); err != nil {
return nil, err
}
issue = &Issue{}
err = res.Unmarshal(issue)
return
}
func (client *Client) FetchComments(project *Project, number string) (comments []Comment, err error) {
api, err := client.simpleApi()
if err != nil {
return
}
res, err := api.Get(fmt.Sprintf("repos/%s/%s/issues/%s/comments", project.Owner, project.Name, number))
if err = checkStatus(200, "fetching comments for issue", res, err); err != nil {
return nil, err
}
comments = []Comment{}
err = res.Unmarshal(&comments)
return
}
func (client *Client) CreateIssue(project *Project, params interface{}) (issue *Issue, err error) {
api, err := client.simpleApi()
if err != nil {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册