From 4132aabf32af6ca42f6603acb26a420222146e21 Mon Sep 17 00:00:00 2001 From: justusbunsi <61625851+justusbunsi@users.noreply.github.com> Date: Sun, 26 Sep 2021 16:05:29 +0200 Subject: [PATCH 1/9] Add labels to pulls list --- modules/print/pull.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/print/pull.go b/modules/print/pull.go index 4fda110..932ecc0 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -122,6 +122,7 @@ func PullsList(prs []*gitea.PullRequest, output string) { "Author", "Milestone", "Updated", + "Labels", ) for _, pr := range prs { @@ -136,6 +137,11 @@ func PullsList(prs []*gitea.PullRequest, output string) { if pr.Milestone != nil { mile = pr.Milestone.Title } + labels := make([]string, len(pr.Labels)) + for i, l := range pr.Labels { + labels[i] = formatLabel(l, !isMachineReadable(output), "") + } + t.addRow( strconv.FormatInt(pr.Index, 10), pr.Title, @@ -143,6 +149,7 @@ func PullsList(prs []*gitea.PullRequest, output string) { author, mile, FormatTime(*pr.Updated), + strings.Join(labels, " "), ) } -- 2.40.1 From 0e18e1130b291ca6202a75f381f8bc72af888cb6 Mon Sep 17 00:00:00 2001 From: justusbunsi Date: Sun, 26 Sep 2021 18:46:20 +0200 Subject: [PATCH 2/9] Support additional flags for output --- cmd/pulls/list.go | 13 +++- modules/print/formatters.go | 13 ++++ modules/print/issue.go | 12 ++-- modules/print/pull.go | 135 ++++++++++++++++++++++++++---------- modules/print/repo.go | 4 +- modules/print/table.go | 6 +- modules/print/times.go | 4 +- 7 files changed, 136 insertions(+), 51 deletions(-) diff --git a/cmd/pulls/list.go b/cmd/pulls/list.go index 5037b48..54f3a1a 100644 --- a/cmd/pulls/list.go +++ b/cmd/pulls/list.go @@ -13,6 +13,10 @@ import ( "github.com/urfave/cli/v2" ) +var pullFieldsFlag = flags.FieldsFlag(print.PullFields, []string{ + "index", "title", "state", "author", "milestone", "updated", "labels", +}) + // CmdPullsList represents a sub command of issues to list pulls var CmdPullsList = cli.Command{ Name: "list", @@ -20,7 +24,7 @@ var CmdPullsList = cli.Command{ Usage: "List pull requests of the repository", Description: `List pull requests of the repository`, Action: RunPullsList, - Flags: flags.IssuePRFlags, + Flags: append([]cli.Flag{pullFieldsFlag}, flags.IssuePRFlags...), } // RunPullsList return list of pulls @@ -46,6 +50,11 @@ func RunPullsList(cmd *cli.Context) error { return err } - print.PullsList(prs, ctx.Output) + fields, err := pullFieldsFlag.GetValues(cmd) + if err != nil { + return err + } + + print.PullsList(prs, ctx.Output, fields) return nil } diff --git a/modules/print/formatters.go b/modules/print/formatters.go index e5a6d88..5ca1b33 100644 --- a/modules/print/formatters.go +++ b/modules/print/formatters.go @@ -72,3 +72,16 @@ func formatUserName(u *gitea.User) string { } return u.FullName } + +func formatBoolean(b bool, allowIcons bool) string { + if !allowIcons { + return fmt.Sprintf("%v", b) + } + + var styled string + if styled = "✓"; !b { + styled = "❌" + } + + return styled +} diff --git a/modules/print/issue.go b/modules/print/issue.go index 5e52898..1273184 100644 --- a/modules/print/issue.go +++ b/modules/print/issue.go @@ -52,30 +52,30 @@ var IssueFields = []string{ } func printIssues(issues []*gitea.Issue, output string, fields []string) { - labelMap := map[int64]string{} + labelMap := map[int64]*gitea.Label{} var printables = make([]printable, len(issues)) for i, x := range issues { // pre-serialize labels for performance for _, label := range x.Labels { if _, ok := labelMap[label.ID]; !ok { - labelMap[label.ID] = formatLabel(label, !isMachineReadable(output), "") + labelMap[label.ID] = label } } // store items with printable interface printables[i] = &printableIssue{x, &labelMap} } - t := tableFromItems(fields, printables) + t := tableFromItems(fields, printables, isMachineReadable(output)) t.print(output) } type printableIssue struct { *gitea.Issue - formattedLabels *map[int64]string + formattedLabels *map[int64]*gitea.Label } -func (x printableIssue) FormatField(field string) string { +func (x printableIssue) FormatField(field string, machineReadable bool) string { switch field { case "index": return fmt.Sprintf("%d", x.Index) @@ -113,7 +113,7 @@ func (x printableIssue) FormatField(field string) string { case "labels": var labels = make([]string, len(x.Labels)) for i, l := range x.Labels { - labels[i] = (*x.formattedLabels)[l.ID] + labels[i] = formatLabel((*x.formattedLabels)[l.ID], !machineReadable, "") } return strings.Join(labels, " ") case "assignees": diff --git a/modules/print/pull.go b/modules/print/pull.go index 932ecc0..fbb3ea6 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -6,7 +6,6 @@ package print import ( "fmt" - "strconv" "strings" "code.gitea.io/sdk/gitea" @@ -114,44 +113,108 @@ func formatReviews(reviews []*gitea.PullReview) string { } // PullsList prints a listing of pulls -func PullsList(prs []*gitea.PullRequest, output string) { - t := tableWithHeader( - "Index", - "Title", - "State", - "Author", - "Milestone", - "Updated", - "Labels", - ) +func PullsList(prs []*gitea.PullRequest, output string, fields []string) { + printPulls(prs, output, fields) +} - 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 - } - labels := make([]string, len(pr.Labels)) - for i, l := range pr.Labels { - labels[i] = formatLabel(l, !isMachineReadable(output), "") - } +// PullFields are all available fields to print with PullsList() +var PullFields = []string{ + "index", + "state", + "author", + "author-id", + "url", - t.addRow( - strconv.FormatInt(pr.Index, 10), - pr.Title, - string(pr.State), - author, - mile, - FormatTime(*pr.Updated), - strings.Join(labels, " "), - ) + "title", + "body", + + "mergeable", + + "created", + "updated", + "deadline", + + "assignees", + "milestone", + "labels", + "comments", +} + +func printPulls(pulls []*gitea.PullRequest, output string, fields []string) { + labelMap := map[int64]*gitea.Label{} + var printables = make([]printable, len(pulls)) + + for i, x := range pulls { + // pre-serialize labels for performance + for _, label := range x.Labels { + if _, ok := labelMap[label.ID]; !ok { + labelMap[label.ID] = label + } + } + // store items with printable interface + printables[i] = &printablePull{x, &labelMap} } + t := tableFromItems(fields, printables, isMachineReadable(output)) t.print(output) } + +type printablePull struct { + *gitea.PullRequest + formattedLabels *map[int64]*gitea.Label +} + +func (x printablePull) FormatField(field string, machineReadable bool) string { + switch field { + case "index": + return fmt.Sprintf("%d", x.Index) + case "state": + return string(x.State) + case "kind": + if x.PullRequest != nil { + return "Pull" + } + return "Issue" + case "author": + return formatUserName(x.Poster) + case "author-id": + return x.Poster.UserName + case "url": + return x.HTMLURL + case "title": + return x.Title + case "body": + return x.Body + case "created": + return FormatTime(*x.Created) + case "updated": + return FormatTime(*x.Updated) + case "deadline": + if x.Deadline == nil { + return "" + } + return FormatTime(*x.Deadline) + case "milestone": + if x.Milestone != nil { + return x.Milestone.Title + } + return "" + case "labels": + var labels = make([]string, len(x.Labels)) + for i, l := range x.Labels { + labels[i] = formatLabel((*x.formattedLabels)[l.ID], !machineReadable, "") + } + return strings.Join(labels, " ") + case "assignees": + var assignees = make([]string, len(x.Assignees)) + for i, a := range x.Assignees { + assignees[i] = formatUserName(a) + } + return strings.Join(assignees, " ") + case "comments": + return fmt.Sprintf("%d", x.Comments) + case "mergeable": + return formatBoolean(x.Mergeable, !machineReadable) + } + return "" +} diff --git a/modules/print/repo.go b/modules/print/repo.go index 9a0d812..dbe193a 100644 --- a/modules/print/repo.go +++ b/modules/print/repo.go @@ -18,7 +18,7 @@ func ReposList(repos []*gitea.Repository, output string, fields []string) { for i, r := range repos { printables[i] = &printableRepo{r} } - t := tableFromItems(fields, printables) + t := tableFromItems(fields, printables, isMachineReadable(output)) t.print(output) } @@ -107,7 +107,7 @@ var RepoFields = []string{ type printableRepo struct{ *gitea.Repository } -func (x printableRepo) FormatField(field string) string { +func (x printableRepo) FormatField(field string, machineReadable bool) string { switch field { case "description": return x.Description diff --git a/modules/print/table.go b/modules/print/table.go index 498fe58..7f6988b 100644 --- a/modules/print/table.go +++ b/modules/print/table.go @@ -24,16 +24,16 @@ type table struct { // printable can be implemented for structs to put fields dynamically into a table type printable interface { - FormatField(field string) string + FormatField(field string, machineReadable bool) string } // high level api to print a table of items with dynamic fields -func tableFromItems(fields []string, values []printable) table { +func tableFromItems(fields []string, values []printable, machineReadable bool) table { t := table{headers: fields} for _, v := range values { row := make([]string, len(fields)) for i, f := range fields { - row[i] = v.FormatField(f) + row[i] = v.FormatField(f, machineReadable) } t.addRowSlice(row) } diff --git a/modules/print/times.go b/modules/print/times.go index 0fbfc3b..deb04e1 100644 --- a/modules/print/times.go +++ b/modules/print/times.go @@ -18,7 +18,7 @@ func TrackedTimesList(times []*gitea.TrackedTime, outputType string, fields []st totalDuration += t.Time printables[i] = &printableTrackedTime{t, outputType} } - t := tableFromItems(fields, printables) + t := tableFromItems(fields, printables, isMachineReadable(outputType)) if printTotal { total := make([]string, len(fields)) @@ -45,7 +45,7 @@ type printableTrackedTime struct { outputFormat string } -func (t printableTrackedTime) FormatField(field string) string { +func (t printableTrackedTime) FormatField(field string, machineReadable bool) string { switch field { case "id": return fmt.Sprintf("%d", t.ID) -- 2.40.1 From 77b12445315ea5d317a387d421022c69ac9ab98f Mon Sep 17 00:00:00 2001 From: justusbunsi Date: Sun, 26 Sep 2021 19:13:50 +0200 Subject: [PATCH 3/9] Switch icons for bool formatting --- modules/print/formatters.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/print/formatters.go b/modules/print/formatters.go index 5ca1b33..1792a1b 100644 --- a/modules/print/formatters.go +++ b/modules/print/formatters.go @@ -79,8 +79,8 @@ func formatBoolean(b bool, allowIcons bool) string { } var styled string - if styled = "✓"; !b { - styled = "❌" + if styled = "✔"; !b { + styled = "✖" } return styled -- 2.40.1 From 1349925308d50b078b4369bc906a7d90d0648d06 Mon Sep 17 00:00:00 2001 From: justusbunsi Date: Mon, 27 Sep 2021 07:05:56 +0200 Subject: [PATCH 4/9] Remove useless kind field for pulls --- modules/print/pull.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/print/pull.go b/modules/print/pull.go index fbb3ea6..ad514ae 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -170,11 +170,6 @@ func (x printablePull) FormatField(field string, machineReadable bool) string { return fmt.Sprintf("%d", x.Index) case "state": return string(x.State) - case "kind": - if x.PullRequest != nil { - return "Pull" - } - return "Issue" case "author": return formatUserName(x.Poster) case "author-id": -- 2.40.1 From c3e7885412a5798f5f6cec3f06f39fcee1b4031e Mon Sep 17 00:00:00 2001 From: justusbunsi Date: Mon, 27 Sep 2021 07:08:17 +0200 Subject: [PATCH 5/9] Reimplement performance optimization for labels --- modules/print/issue.go | 11 ++++++----- modules/print/pull.go | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/modules/print/issue.go b/modules/print/issue.go index 1273184..4f52455 100644 --- a/modules/print/issue.go +++ b/modules/print/issue.go @@ -52,27 +52,28 @@ var IssueFields = []string{ } func printIssues(issues []*gitea.Issue, output string, fields []string) { - labelMap := map[int64]*gitea.Label{} + labelMap := map[int64]string{} var printables = make([]printable, len(issues)) + machineReadable := isMachineReadable(output) for i, x := range issues { // pre-serialize labels for performance for _, label := range x.Labels { if _, ok := labelMap[label.ID]; !ok { - labelMap[label.ID] = label + labelMap[label.ID] = formatLabel(label, !machineReadable, "") } } // store items with printable interface printables[i] = &printableIssue{x, &labelMap} } - t := tableFromItems(fields, printables, isMachineReadable(output)) + t := tableFromItems(fields, printables, machineReadable) t.print(output) } type printableIssue struct { *gitea.Issue - formattedLabels *map[int64]*gitea.Label + formattedLabels *map[int64]string } func (x printableIssue) FormatField(field string, machineReadable bool) string { @@ -113,7 +114,7 @@ func (x printableIssue) FormatField(field string, machineReadable bool) string { case "labels": var labels = make([]string, len(x.Labels)) for i, l := range x.Labels { - labels[i] = formatLabel((*x.formattedLabels)[l.ID], !machineReadable, "") + labels[i] = (*x.formattedLabels)[l.ID] } return strings.Join(labels, " ") case "assignees": diff --git a/modules/print/pull.go b/modules/print/pull.go index ad514ae..4f3ca6a 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -141,27 +141,28 @@ var PullFields = []string{ } func printPulls(pulls []*gitea.PullRequest, output string, fields []string) { - labelMap := map[int64]*gitea.Label{} + labelMap := map[int64]string{} var printables = make([]printable, len(pulls)) + machineReadable := isMachineReadable(output) for i, x := range pulls { // pre-serialize labels for performance for _, label := range x.Labels { if _, ok := labelMap[label.ID]; !ok { - labelMap[label.ID] = label + labelMap[label.ID] = formatLabel(label, !machineReadable, "") } } // store items with printable interface printables[i] = &printablePull{x, &labelMap} } - t := tableFromItems(fields, printables, isMachineReadable(output)) + t := tableFromItems(fields, printables, machineReadable) t.print(output) } type printablePull struct { *gitea.PullRequest - formattedLabels *map[int64]*gitea.Label + formattedLabels *map[int64]string } func (x printablePull) FormatField(field string, machineReadable bool) string { @@ -197,7 +198,7 @@ func (x printablePull) FormatField(field string, machineReadable bool) string { case "labels": var labels = make([]string, len(x.Labels)) for i, l := range x.Labels { - labels[i] = formatLabel((*x.formattedLabels)[l.ID], !machineReadable, "") + labels[i] = (*x.formattedLabels)[l.ID] } return strings.Join(labels, " ") case "assignees": -- 2.40.1 From c65cd5817053a6d592ea5c6a42f82735543ff35d Mon Sep 17 00:00:00 2001 From: Norwin Date: Mon, 27 Sep 2021 13:44:42 +0200 Subject: [PATCH 6/9] refactor --- modules/print/formatters.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/print/formatters.go b/modules/print/formatters.go index 1792a1b..af7a899 100644 --- a/modules/print/formatters.go +++ b/modules/print/formatters.go @@ -78,8 +78,8 @@ func formatBoolean(b bool, allowIcons bool) string { return fmt.Sprintf("%v", b) } - var styled string - if styled = "✔"; !b { + styled := "✔" + if !b { styled = "✖" } -- 2.40.1 From 4263af605f175163f484198328796f46eb382bfe Mon Sep 17 00:00:00 2001 From: Norwin Date: Mon, 27 Sep 2021 14:41:13 +0200 Subject: [PATCH 7/9] refactor: reusable PR field formatters --- modules/print/pull.go | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/modules/print/pull.go b/modules/print/pull.go index 4f3ca6a..00b01f9 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -22,19 +22,8 @@ var ciStatusSymbols = map[gitea.StatusState]string{ // PullDetails print an pull rendered to stdout func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview, ciStatus *gitea.CombinedStatus) { 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 - } - } - - state := pr.State - if pr.Merged != nil { - state = "merged" - } + head := formatPRHead(pr) + state := formatPRState(pr) out := fmt.Sprintf( "# #%d %s (%s)\n@%s created %s\t**%s** <- **%s**\n\n%s\n\n", @@ -78,6 +67,25 @@ func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview, ciStatus *g outputMarkdown(out, pr.HTMLURL) } +func formatPRHead(pr *gitea.PullRequest) string { + 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 + } + } + return head +} + +func formatPRState(pr *gitea.PullRequest) string { + if pr.Merged != nil { + return "merged" + } + return string(pr.State) +} + func formatReviews(reviews []*gitea.PullReview) string { result := "" if len(reviews) == 0 { @@ -170,7 +178,7 @@ func (x printablePull) FormatField(field string, machineReadable bool) string { case "index": return fmt.Sprintf("%d", x.Index) case "state": - return string(x.State) + return formatPRState(x.PullRequest) case "author": return formatUserName(x.Poster) case "author-id": -- 2.40.1 From eca473bab49ab2beb6f47398d55e5b361539b9eb Mon Sep 17 00:00:00 2001 From: Norwin Date: Mon, 27 Sep 2021 14:42:05 +0200 Subject: [PATCH 8/9] add more PR fields --- modules/print/pull.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/modules/print/pull.go b/modules/print/pull.go index 00b01f9..5ba5997 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -137,6 +137,11 @@ var PullFields = []string{ "body", "mergeable", + "base", + "base-commit", + "head", + "diff", + "patch", "created", "updated", @@ -219,6 +224,16 @@ func (x printablePull) FormatField(field string, machineReadable bool) string { return fmt.Sprintf("%d", x.Comments) case "mergeable": return formatBoolean(x.Mergeable, !machineReadable) + case "base": + return x.Base.Ref + case "base-commit": + return x.MergeBase + case "head": + return formatPRHead(x.PullRequest) + case "diff": + return x.DiffURL + case "patch": + return x.PatchURL } return "" } -- 2.40.1 From 316ef0c6ea7328897066d918c94357d655131717 Mon Sep 17 00:00:00 2001 From: Norwin Date: Mon, 27 Sep 2021 14:45:44 +0200 Subject: [PATCH 9/9] be smarter about mergeable info --- modules/print/pull.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/print/pull.go b/modules/print/pull.go index 5ba5997..5007bde 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -223,7 +223,8 @@ func (x printablePull) FormatField(field string, machineReadable bool) string { case "comments": return fmt.Sprintf("%d", x.Comments) case "mergeable": - return formatBoolean(x.Mergeable, !machineReadable) + isMergeable := x.Mergeable && x.State == gitea.StateOpen + return formatBoolean(isMergeable, !machineReadable) case "base": return x.Base.Ref case "base-commit": -- 2.40.1