package redmine import ( "context" "fmt" "strings" ) // enumeration endpoints: trackers, statuses, priorities. The CLI maps // human names ("done", "feature", "immediate") onto ids through these; // the harness gets the same surface so there is no copy-paste temptation. type trackerList struct { Trackers []Ref `json:"trackers"` } type statusList struct { Statuses []StatusRef `json:"issue_statuses"` } type priorityList struct { Priorities []Ref `json:"issue_priorities"` } // ListTrackers returns the server's issue trackers. func (c *Client) ListTrackers(ctx context.Context) ([]Ref, error) { var body trackerList if err := c.do(ctx, "GET", "/trackers.json", nil, nil, &body); err != nil { return nil, err } return body.Trackers, nil } // ListStatuses returns the server's issue statuses (with is_closed). func (c *Client) ListStatuses(ctx context.Context) ([]StatusRef, error) { var body statusList if err := c.do(ctx, "GET", "/issue_statuses.json", nil, nil, &body); err != nil { return nil, err } return body.Statuses, nil } // ListPriorities returns the server's issue priorities. func (c *Client) ListPriorities(ctx context.Context) ([]Ref, error) { var body priorityList if err := c.do(ctx, "GET", "/enumerations/issue_priorities.json", nil, nil, &body); err != nil { return nil, err } return body.Priorities, nil } // StatusIDByName resolves a status name case-insensitively ("done" -> // Done's id). Unknown names are ErrNotFound; the name, never any server // body, appears in the message. func (c *Client) StatusIDByName(ctx context.Context, name string) (int, error) { list, err := c.ListStatuses(ctx) if err != nil { return 0, err } for _, s := range list { if strings.EqualFold(s.Name, name) { return s.ID, nil } } return 0, fmt.Errorf("%w: status %q", ErrNotFound, name) } // TrackerIDByName resolves a tracker name case-insensitively. func (c *Client) TrackerIDByName(ctx context.Context, name string) (int, error) { list, err := c.ListTrackers(ctx) if err != nil { return 0, err } for _, t := range list { if strings.EqualFold(t.Name, name) { return t.ID, nil } } return 0, fmt.Errorf("%w: tracker %q", ErrNotFound, name) } // PriorityIDByName resolves a priority name case-insensitively. func (c *Client) PriorityIDByName(ctx context.Context, name string) (int, error) { list, err := c.ListPriorities(ctx) if err != nil { return 0, err } for _, p := range list { if strings.EqualFold(p.Name, name) { return p.ID, nil } } return 0, fmt.Errorf("%w: priority %q", ErrNotFound, name) } // VersionIDByName resolves a version name within a project, // case-insensitively. func (c *Client) VersionIDByName(ctx context.Context, project, name string) (int, error) { list, err := c.ListVersions(ctx, project) if err != nil { return 0, err } for _, v := range list { if strings.EqualFold(v.Name, name) { return v.ID, nil } } return 0, fmt.Errorf("%w: version %q in %s", ErrNotFound, name, project) } // CategoryIDByName resolves a category name within a project, // case-insensitively. func (c *Client) CategoryIDByName(ctx context.Context, project, name string) (int, error) { list, err := c.ListCategories(ctx, project) if err != nil { return 0, err } for _, cat := range list { if strings.EqualFold(cat.Name, name) { return cat.ID, nil } } return 0, fmt.Errorf("%w: category %q in %s", ErrNotFound, name, project) }