Issues (create/update/partial PUT, notes-as-journals), versions, categories, relations, and name-to-id resolution over trackers/ statuses/priorities. Sentinel errors carry http codes one-line; response bodies are never surfaced so the API key cannot leak through error strings (the fake deliberately echoes the presented key to prove it).
123 lines
3.4 KiB
Go
123 lines
3.4 KiB
Go
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)
|
|
}
|