mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
fix(milestone): address milestones by title or ID everywhere
milestone view v2.0 failed with "invalid resource number" although its usage promised <id-or-name>, and issue create --milestone v1.0 failed with a strconv error. Every milestone argument (view, edit, delete, close, reopen, milestone issue add|remove|list) and issue create|edit -m/--milestone now accept a title or an ID: a number is an ID first, then a title; --by-name matches numeric titles only. --milestone-name stays as a hidden name of --milestone, and issue edit gains --remove-milestone (as does --milestone 0). Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
12 files changed
+220
-147
No files matched your search
@@ -4,7 +4,6 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -14,35 +13,19 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// milestoneSelector validates a milestone ID or, with byName, a title before any request.
|
||||
func milestoneSelector(selector string, byName bool) (int64, error) {
|
||||
if byName {
|
||||
if strings.TrimSpace(selector) == "" {
|
||||
return 0, clierr.Wrap(clierr.Usage, errors.New("milestone name cannot be empty"))
|
||||
}
|
||||
return 0, nil
|
||||
// findMilestone resolves a milestone argument, a title or an ID, in the target repository.
|
||||
func findMilestone(cmd *cobra.Command, t target, raw string, byName bool) (services.Milestone, error) {
|
||||
if strings.TrimSpace(raw) == "" {
|
||||
return services.Milestone{}, clierr.Wrap(clierr.Usage, errors.New("milestone title or ID cannot be empty"))
|
||||
}
|
||||
return number(selector)
|
||||
}
|
||||
|
||||
// existingMilestone resolves a title, or confirms that an ID exists.
|
||||
func existingMilestone(ctx context.Context, milestones services.Milestones, selector string, id int64, byName bool) (int64, error) {
|
||||
if byName {
|
||||
return milestones.ResolveName(ctx, selector)
|
||||
}
|
||||
_, err := milestones.View(ctx, id)
|
||||
return id, err
|
||||
return (services.Milestones{Client: t.client, Repository: t.Repo}).FindOne(cmd.Context(), raw, byName)
|
||||
}
|
||||
|
||||
func (a *application) milestoneIssueCommand() *cobra.Command {
|
||||
group := &cobra.Command{Use: "issue", Short: "Manage milestone issues and pull requests"}
|
||||
opts := services.ListOptions{}
|
||||
var byName bool
|
||||
list := &cobra.Command{Use: "list <id-or-name>", Short: "List issues and pull requests in a milestone", Args: argsExact(1), RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id, err := milestoneSelector(args[0], byName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
list := &cobra.Command{Use: "list <milestone>", Short: "List issues and pull requests in a milestone", Args: argsExact(1), RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := oneOf("state", opts.State, "open", "closed", "all"); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -53,11 +36,11 @@ func (a *application) milestoneIssueCommand() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, err = existingMilestone(cmd.Context(), services.Milestones{Client: target.client, Repository: target.Repo}, args[0], id, byName)
|
||||
milestone, err := findMilestone(cmd, target, args[0], byName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts.Milestones = strconv.FormatInt(id, 10)
|
||||
opts.Milestones = strconv.FormatInt(milestone.ID, 10)
|
||||
items, more, err := (services.Issues{Client: target.client, Repository: target.Repo}).List(cmd.Context(), opts)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -70,15 +53,11 @@ func (a *application) milestoneIssueCommand() *cobra.Command {
|
||||
pageFlags(list, &opts.Limit, &opts.Page)
|
||||
list.Flags().StringVar(&opts.State, "state", "open", "open, closed, or all")
|
||||
list.Flags().StringVar(&opts.Kind, "kind", "all", "all, issues, or pulls")
|
||||
list.Flags().BoolVar(&byName, "by-name", false, "Select by exact milestone title instead of ID")
|
||||
list.Flags().BoolVar(&byName, "by-name", false, "Match a numeric argument as a milestone title rather than an ID")
|
||||
group.AddCommand(list)
|
||||
for _, verb := range []string{"add", "remove"} {
|
||||
var byName bool
|
||||
command := &cobra.Command{Use: verb + " <id-or-name> <number>...", Short: titleCase(verb) + " issues or pull requests in a milestone", Args: usageArgs(cobra.MinimumNArgs(2)), RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id, err := milestoneSelector(args[0], byName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
command := &cobra.Command{Use: verb + " <milestone> <number>...", Short: titleCase(verb) + " issues or pull requests in a milestone", Args: usageArgs(cobra.MinimumNArgs(2)), RunE: func(cmd *cobra.Command, args []string) error {
|
||||
numbers, err := resourceNumbers(args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -87,10 +66,11 @@ func (a *application) milestoneIssueCommand() *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, err = existingMilestone(cmd.Context(), services.Milestones{Client: target.client, Repository: target.Repo}, args[0], id, byName)
|
||||
milestone, err := findMilestone(cmd, target, args[0], byName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id := milestone.ID
|
||||
service := services.Issues{Client: target.client, Repository: target.Repo}
|
||||
return batch(a, cmd, numbers, issueLabel, func(n int64) (services.Issue, error) {
|
||||
if verb == "remove" {
|
||||
@@ -99,7 +79,7 @@ func (a *application) milestoneIssueCommand() *cobra.Command {
|
||||
return service.Edit(cmd.Context(), n, services.IssueEdit{Milestone: &id})
|
||||
}, issueRow)
|
||||
}}
|
||||
command.Flags().BoolVar(&byName, "by-name", false, "Select by exact milestone title instead of ID")
|
||||
command.Flags().BoolVar(&byName, "by-name", false, "Match a numeric argument as a milestone title rather than an ID")
|
||||
group.AddCommand(command)
|
||||
}
|
||||
return group
|
||||
|
||||
Reference in new issue
Block a user