2020-09-30 13:11:33 +08:00
|
|
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a MIT-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package print
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-12-08 18:28:54 +08:00
|
|
|
"strconv"
|
2020-12-17 01:16:50 +08:00
|
|
|
"strings"
|
2020-09-30 13:11:33 +08:00
|
|
|
|
|
|
|
"code.gitea.io/sdk/gitea"
|
|
|
|
)
|
|
|
|
|
2020-12-17 01:16:50 +08:00
|
|
|
var ciStatusSymbols = map[gitea.StatusState]string{
|
|
|
|
gitea.StatusSuccess: "✓ ",
|
|
|
|
gitea.StatusPending: "⭮ ",
|
|
|
|
gitea.StatusWarning: "⚠ ",
|
|
|
|
gitea.StatusError: "✘ ",
|
|
|
|
gitea.StatusFailure: "❌ ",
|
|
|
|
}
|
|
|
|
|
2020-09-30 13:11:33 +08:00
|
|
|
// PullDetails print an pull rendered to stdout
|
2020-12-17 01:16:50 +08:00
|
|
|
func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview, ciStatus *gitea.CombinedStatus) {
|
2020-12-08 12:06:05 +08:00
|
|
|
base := pr.Base.Name
|
|
|
|
head := pr.Head.Name
|
|
|
|
if pr.Head.RepoID != pr.Base.RepoID {
|
|
|
|
if pr.Head.Repository != nil {
|
|
|
|
head = pr.Head.Repository.Owner.UserName + ":" + head
|
|
|
|
} else {
|
|
|
|
head = "delete:" + head
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-17 01:16:50 +08:00
|
|
|
state := pr.State
|
|
|
|
if pr.Merged != nil {
|
|
|
|
state = "merged"
|
|
|
|
}
|
|
|
|
|
2020-12-08 12:06:05 +08:00
|
|
|
out := fmt.Sprintf(
|
2020-12-17 01:16:50 +08:00
|
|
|
"# #%d %s (%s)\n@%s created %s\t**%s** <- **%s**\n\n%s\n\n",
|
2020-10-05 10:23:57 +08:00
|
|
|
pr.Index,
|
2020-09-30 13:11:33 +08:00
|
|
|
pr.Title,
|
2020-12-17 01:16:50 +08:00
|
|
|
state,
|
2020-09-30 13:11:33 +08:00
|
|
|
pr.Poster.UserName,
|
2020-10-05 20:23:32 +08:00
|
|
|
FormatTime(*pr.Created),
|
2020-12-08 12:06:05 +08:00
|
|
|
base,
|
|
|
|
head,
|
2020-09-30 13:11:33 +08:00
|
|
|
pr.Body,
|
2020-12-08 12:06:05 +08:00
|
|
|
)
|
|
|
|
|
2020-12-17 01:16:50 +08:00
|
|
|
if ciStatus != nil || len(reviews) != 0 || pr.State == gitea.StateOpen {
|
|
|
|
out += "---\n"
|
|
|
|
}
|
|
|
|
|
|
|
|
out += formatReviews(reviews)
|
|
|
|
|
|
|
|
if ciStatus != nil {
|
|
|
|
var summary, errors string
|
|
|
|
for _, s := range ciStatus.Statuses {
|
|
|
|
summary += ciStatusSymbols[s.State]
|
|
|
|
if s.State != gitea.StatusSuccess {
|
|
|
|
errors += fmt.Sprintf(" - [**%s**:\t%s](%s)\n", s.Context, s.Description, s.TargetURL)
|
2020-12-08 12:06:05 +08:00
|
|
|
}
|
|
|
|
}
|
2020-12-17 01:16:50 +08:00
|
|
|
if len(ciStatus.Statuses) != 0 {
|
|
|
|
out += fmt.Sprintf("- CI: %s\n%s", summary, errors)
|
2020-12-08 12:06:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-17 01:16:50 +08:00
|
|
|
if pr.State == gitea.StateOpen {
|
|
|
|
if pr.Mergeable {
|
|
|
|
out += "- No Conflicts\n"
|
|
|
|
} else {
|
|
|
|
out += "- **Conflicting files**\n"
|
|
|
|
}
|
2020-12-08 12:06:05 +08:00
|
|
|
}
|
|
|
|
|
2021-03-12 20:28:46 +08:00
|
|
|
outputMarkdown(out, pr.HTMLURL)
|
2020-12-08 18:28:54 +08:00
|
|
|
}
|
|
|
|
|
2020-12-17 01:16:50 +08:00
|
|
|
func formatReviews(reviews []*gitea.PullReview) string {
|
|
|
|
result := ""
|
|
|
|
if len(reviews) == 0 {
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// deduplicate reviews by user (via review time & userID),
|
|
|
|
reviewByUser := make(map[int64]*gitea.PullReview)
|
|
|
|
for _, review := range reviews {
|
|
|
|
switch review.State {
|
|
|
|
case gitea.ReviewStateApproved,
|
|
|
|
gitea.ReviewStateRequestChanges,
|
|
|
|
gitea.ReviewStateRequestReview:
|
|
|
|
if r, ok := reviewByUser[review.Reviewer.ID]; !ok || review.Submitted.After(r.Submitted) {
|
|
|
|
reviewByUser[review.Reviewer.ID] = review
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// group reviews by type
|
|
|
|
usersByState := make(map[gitea.ReviewStateType][]string)
|
|
|
|
for _, r := range reviewByUser {
|
|
|
|
u := r.Reviewer.UserName
|
|
|
|
users := usersByState[r.State]
|
|
|
|
usersByState[r.State] = append(users, u)
|
|
|
|
}
|
|
|
|
|
|
|
|
// stringify
|
|
|
|
for state, user := range usersByState {
|
|
|
|
result += fmt.Sprintf("- %s by @%s\n", state, strings.Join(user, ", @"))
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-12-08 18:28:54 +08:00
|
|
|
// PullsList prints a listing of pulls
|
|
|
|
func PullsList(prs []*gitea.PullRequest, output string) {
|
2020-12-10 06:04:36 +08:00
|
|
|
t := tableWithHeader(
|
2020-12-08 18:28:54 +08:00
|
|
|
"Index",
|
|
|
|
"Title",
|
|
|
|
"State",
|
|
|
|
"Author",
|
|
|
|
"Milestone",
|
|
|
|
"Updated",
|
2020-12-10 06:04:36 +08:00
|
|
|
)
|
2020-12-08 18:28:54 +08:00
|
|
|
|
|
|
|
for _, pr := range prs {
|
|
|
|
if pr == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
author := pr.Poster.FullName
|
|
|
|
if len(author) == 0 {
|
|
|
|
author = pr.Poster.UserName
|
|
|
|
}
|
|
|
|
mile := ""
|
|
|
|
if pr.Milestone != nil {
|
|
|
|
mile = pr.Milestone.Title
|
|
|
|
}
|
2020-12-10 06:04:36 +08:00
|
|
|
t.addRow(
|
|
|
|
strconv.FormatInt(pr.Index, 10),
|
|
|
|
pr.Title,
|
|
|
|
string(pr.State),
|
|
|
|
author,
|
|
|
|
mile,
|
|
|
|
FormatTime(*pr.Updated),
|
2020-12-08 18:28:54 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-12-10 06:04:36 +08:00
|
|
|
t.print(output)
|
2020-09-30 13:11:33 +08:00
|
|
|
}
|