diff --git a/commands/issue.go b/commands/issue.go index eb2de646f0073b3b79d9f9a560e96d219a33e3ca..53945e3b9a2731ce0493660ec448aff3571a5e23 100644 --- a/commands/issue.go +++ b/commands/issue.go @@ -332,15 +332,6 @@ func formatIssuePlaceholders(issue github.Issue, colorize bool) map[string]strin assignees = append(assignees, assignee.Login) } - var requestedReviewers []string - for _, requestedReviewer := range issue.RequestedReviewers { - requestedReviewers = append(requestedReviewers, requestedReviewer.Login) - } - for _, requestedTeam := range issue.RequestedTeams { - teamSlug := fmt.Sprintf("%s/%s", issue.Base.Repo.Owner.Login, requestedTeam.Slug) - requestedReviewers = append(requestedReviewers, teamSlug) - } - var milestoneNumber, milestoneTitle string if issue.Milestone != nil { milestoneNumber = fmt.Sprintf("%d", issue.Milestone.Number) @@ -380,7 +371,6 @@ func formatIssuePlaceholders(issue github.Issue, colorize bool) map[string]strin "b": issue.Body, "au": issue.User.Login, "as": strings.Join(assignees, ", "), - "rs": strings.Join(requestedReviewers, ", "), "Mn": milestoneNumber, "Mt": milestoneTitle, "NC": numComments, @@ -396,6 +386,44 @@ func formatIssuePlaceholders(issue github.Issue, colorize bool) map[string]strin } } +func formatPullRequestPlaceholders(pr github.PullRequest) map[string]string { + base := pr.Base.Ref + head := pr.Head.Label + if pr.IsSameRepo() { + head = pr.Head.Ref + } + + var requestedReviewers []string + for _, requestedReviewer := range pr.RequestedReviewers { + requestedReviewers = append(requestedReviewers, requestedReviewer.Login) + } + for _, requestedTeam := range pr.RequestedTeams { + teamSlug := fmt.Sprintf("%s/%s", pr.Base.Repo.Owner.Login, requestedTeam.Slug) + requestedReviewers = append(requestedReviewers, teamSlug) + } + + var mergedDate, mergedAtISO8601, mergedAtUnix, mergedAtRelative string + if !pr.MergedAt.IsZero() { + mergedDate = pr.MergedAt.Format("02 Jan 2006") + mergedAtISO8601 = pr.MergedAt.Format(time.RFC3339) + mergedAtUnix = fmt.Sprintf("%d", pr.MergedAt.Unix()) + mergedAtRelative = utils.TimeAgo(pr.MergedAt) + } + + return map[string]string{ + "B": base, + "H": head, + "sB": pr.Base.Sha, + "sH": pr.Head.Sha, + "sm": pr.MergeCommitSha, + "rs": strings.Join(requestedReviewers, ", "), + "mD": mergedDate, + "mI": mergedAtISO8601, + "mt": mergedAtUnix, + "mr": mergedAtRelative, + } +} + func formatIssue(issue github.Issue, format string, colorize bool) string { placeholders := formatIssuePlaceholders(issue, colorize) return ui.Expand(format, placeholders, colorize) diff --git a/commands/pr.go b/commands/pr.go index ed48443395edae4e4aaa57116d16d3452095d097..8ef8952971e563fa6d4ba42dce6d280c6504cf82 100644 --- a/commands/pr.go +++ b/commands/pr.go @@ -31,7 +31,8 @@ pr checkout [] ## Options: -s, --state - Filter pull requests by (default: "open"). + Filter pull requests by . Supported values are: "open" (default), + "closed", "merged", or "all". -h, --head [:] Show pull requests started from the specified head . The default @@ -52,7 +53,7 @@ pr checkout [] %U: the URL of this pull request - %S: state (i.e. "open", "closed") + %S: state ("open" or "closed") %sC: set color to red or green, depending on pull request state. @@ -66,8 +67,14 @@ pr checkout [] %B: base branch + %sB: base commit SHA + %H: head branch + %sH: head commit SHA + + %sm: merge commit SHA + %au: login name of author %as: comma-separated list of assignees @@ -98,6 +105,14 @@ pr checkout [] %uI: updated date, ISO 8601 format + %mD: merged date-only (no time of day) + + %mr: merged date, relative + + %mt: merged date, UNIX timestamp + + %mI: merged date, ISO 8601 format + -o, --sort Sort displayed issues by "created" (default), "updated", "popularity", or "long-running". @@ -188,7 +203,15 @@ func listPulls(cmd *Command, args *Args) { filters["direction"] = "desc" } - pulls, err := gh.FetchPullRequests(project, filters, flagPullRequestLimit, nil) + onlyMerged := false + if filters["state"] == "merged" { + filters["state"] = "closed" + onlyMerged = true + } + + pulls, err := gh.FetchPullRequests(project, filters, flagPullRequestLimit, func(pr *github.PullRequest) bool { + return !(onlyMerged && pr.MergedAt.IsZero()) + }) utils.Check(err) colorize := ui.IsTerminal(os.Stdout) @@ -229,15 +252,9 @@ func checkoutPr(command *Command, args *Args) { } func formatPullRequest(pr github.PullRequest, format string, colorize bool) string { - base := pr.Base.Ref - head := pr.Head.Label - if pr.IsSameRepo() { - head = pr.Head.Ref - } - placeholders := formatIssuePlaceholders(github.Issue(pr), colorize) - placeholders["B"] = base - placeholders["H"] = head - + for key, value := range formatPullRequestPlaceholders(pr) { + placeholders[key] = value + } return ui.Expand(format, placeholders, colorize) } diff --git a/features/pr-list.feature b/features/pr-list.feature index 61eb809b2a50f5aa99d48ef1fff6b6e09ab346ca..c7964a0393140bf757071c4618ea577af80c815a 100644 --- a/features/pr-list.feature +++ b/features/pr-list.feature @@ -149,3 +149,44 @@ Feature: hub pr list """ When I successfully run `hub pr list -h mislav:patch-1` Then the output should contain exactly "" + + Scenario: Filter by merged state + Given the GitHub API server: + """ + get('/repos/github/hub/pulls') { + assert :state => "closed" + + json [ + { :number => 999, + :title => "First", + :state => "closed", + :merged_at => "2018-12-11T10:50:33Z", + :base => { :ref => "master", :label => "github:master" }, + :head => { :ref => "patch-1", :label => "octocat:patch-1" }, + :user => { :login => "octocat" }, + }, + { :number => 102, + :title => "Second", + :state => "closed", + :merged_at => nil, + :base => { :ref => "master", :label => "github:master" }, + :head => { :ref => "patch-2", :label => "octocat:patch-2" }, + :user => { :login => "octocat" }, + }, + { :number => 13, + :title => "Third", + :state => "closed", + :merged_at => "2018-12-11T10:50:33Z", + :base => { :ref => "master", :label => "github:master" }, + :head => { :ref => "patch-3", :label => "octocat:patch-3" }, + :user => { :login => "octocat" }, + }, + ] + } + """ + When I successfully run `hub pr list --state=merged` + Then the output should contain exactly: + """ + #999 First + #13 Third\n + """ diff --git a/github/client.go b/github/client.go index e75a9ce4d06f166254c18b89f7abbb2a00b27f7c..c27969673498bdbc270ecad0ce8c2bc96f1738c0 100644 --- a/github/client.go +++ b/github/client.go @@ -542,7 +542,8 @@ type Issue struct { Head *PullRequestSpec `json:"head"` Base *PullRequestSpec `json:"base"` - MaintainerCanModify bool `json:"maintainer_can_modify"` + MergeCommitSha string `json:"merge_commit_sha"` + MaintainerCanModify bool `json:"maintainer_can_modify"` Comments int `json:"comments"` Labels []IssueLabel `json:"labels"` @@ -550,6 +551,7 @@ type Issue struct { Milestone *Milestone `json:"milestone"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` + MergedAt time.Time `json:"merged_at"` RequestedReviewers []User `json:"requested_reviewers"` RequestedTeams []Team `json:"requested_teams"`