// Copyright 2026 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package services import ( "context" "fmt" "strconv" "strings" ) // ResolveName selects an exact title across open and closed milestones. func (s Milestones) ResolveName(ctx context.Context, name string) (int64, error) { if strings.TrimSpace(name) == "" { return 0, fmt.Errorf("milestone name cannot be empty") } items, err := s.All(ctx) if err != nil { return 0, err } var id int64 for _, item := range items { if item.Title != name { continue } if id != 0 { return 0, fmt.Errorf("milestone name %q is ambiguous; select its numeric ID", name) } id = item.ID } if id == 0 { return 0, fmt.Errorf("milestone %q does not exist; use tea milestone list --state all", name) } return id, nil } // All returns the open and closed milestones of the repository. func (s Milestones) All(ctx context.Context) ([]Milestone, error) { return listAll(func(page int) ([]Milestone, error) { return s.List(ctx, "all", 100, page) }) } // FilterIDs resolves the milestones that filter an issue listing, each an ID or a title, to their // IDs. Gitea drops filter values that name no milestone and lists every issue when none is left, // so an unknown milestone is an error here. func (s Milestones) FilterIDs(ctx context.Context, values []string) ([]string, error) { items, err := s.All(ctx) if err != nil { return nil, err } finder := NameOrID[Milestone]{Kind: "milestone", Scope: s.Repository, ID: func(m Milestone) int64 { return m.ID }, Name: func(m Milestone) string { return m.Title }} ids := make([]string, len(values)) for i, value := range values { milestone, err := finder.Find(items, value) if err != nil { return nil, err } ids[i] = strconv.FormatInt(milestone.ID, 10) } return ids, nil }