refactor: reuse the existing service and rendering helpers

services.IsNotFound replaces the hand-rolled 404 checks, convertPage
the copied page conversions and lastPathNumber the comment's own
number parser. The List wrappers around ListPage of releases,
branches, wiki pages, secrets and variables go, pull request filters
resolve milestones through Milestones.FindOne like issues, and
localFlagsChanged, boolOrder, Cell.Render, stateBadge and dueText
replace their copies.

Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
bircni committed 2026-10-12 11:22:52 +02:00
1 parent 29f62da006
commit 83924892ff
33 files changed
+85 -212

No files matched your search

+2 -38
View File
@@ -4,9 +4,7 @@
package app
import (
"context"
"errors"
"net/http"
"slices"
"strconv"
"strings"
@@ -14,9 +12,7 @@ import (
"gitea.dev/tea/internal/clierr"
"gitea.dev/tea/internal/services"
"gitea.dev/tea/internal/terminal"
"gitea.dev/tea/internal/transport"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
func (a *application) prCommand() *cobra.Command {
@@ -71,7 +67,7 @@ each pull request, which tea only makes when --json names them.`, Args: argsExac
return err
}
if milestone != "" {
if options.Milestone, err = milestoneFilter(cmd.Context(), t, milestone); err != nil {
if options.Milestone, err = milestoneID(cmd, t, milestone); err != nil {
return err
}
}
@@ -91,7 +87,7 @@ each pull request, which tea only makes when --json names them.`, Args: argsExac
noun := map[string]string{"open": "open pull requests", "closed": "closed pull requests", "merged": "merged pull requests", "all": "pull requests"}[state]
what := noun + " in " + t.Repo
empty := "no " + what
if filtered(cmd, "state", "limit", "page", "sort") {
if localFlagsChanged(cmd, "state", "limit", "page", "sort") {
empty = "no " + noun + " match your filters in " + t.Repo
}
columns := []terminal.Column{{Header: "ID", Prefix: "#"}, {Header: "Title", Flex: true}, {Header: "Branch", Flex: true, Min: 12}, {Header: "State", PipedOnly: state == "open"}, {Header: "Author"}, {Header: "Created"}}
@@ -137,22 +133,6 @@ $ tea pr list --json number,title,head --jq '.[] | select(.head == "feature/logi
return cmd
}
// changedFlags lists the names of the command's own flags that were given.
func changedFlags(cmd *cobra.Command) []string {
var names []string
cmd.LocalNonPersistentFlags().VisitAll(func(flag *pflag.Flag) {
if flag.Changed {
names = append(names, flag.Name)
}
})
return names
}
// filtered reports whether a flag other than those named, which do not filter, was given.
func filtered(cmd *cobra.Command, unfiltered ...string) bool {
return slices.ContainsFunc(changedFlags(cmd), func(name string) bool { return !slices.Contains(unfiltered, name) })
}
// jsonSelects reports whether --json names one of fields, rather than selecting every field.
func (a *application) jsonSelects(fields ...string) bool {
for field := range strings.SplitSeq(a.options.json, ",") {
@@ -163,22 +143,6 @@ func (a *application) jsonSelects(fields ...string) bool {
return false
}
// milestoneFilter resolves a milestone given as an ID or a title (D10): a number is an ID first,
// then a title.
func milestoneFilter(ctx context.Context, t target, raw string) (int64, error) {
service := services.Milestones{Client: t.client, Repository: t.Repo}
if id, err := strconv.ParseInt(raw, 10, 64); err == nil && id > 0 {
_, err := service.View(ctx, id)
if err == nil {
return id, nil
}
if apiErr, ok := errors.AsType[*transport.APIError](err); !ok || apiErr.Status != http.StatusNotFound {
return 0, err
}
}
return service.ResolveName(ctx, raw)
}
func (a *application) pullViewCommand() *cobra.Command {
var web, comments bool
cmd := &cobra.Command{Use: "view [<number> | <url> | <branch>]", Short: "View a pull request", Annotations: pullArgumentsAnnotation(nil), Args: usageArgs(cobra.MaximumNArgs(1)), RunE: func(cmd *cobra.Command, args []string) error {