package wire // The bodies that go up, and the shorthand that fills them. // // The omitted keys carry meaning of their own on a PATCH: a key that is absent // leaves the tracker's value alone, and a key that is present overwrites it. So // "no opinion" and "empty" must not marshal the same way, which is what every // pointer and every omitempty below is for. // IssueRequest is the body of a create or an edit. // // Every field is a pointer because Gitea reads an absent key as "no opinion" // and a present one as "make it this", and the difference is not academic: an // empty `ref` CLEARS the branch an issue is pinned to, and an empty `labels` // clears its labels. A caller meaning to change only the state would do both by // accident with plain zero values. Set fills a field; leaving it nil leaves the // tracker's copy alone. type IssueRequest struct { Title *string `json:"title,omitempty"` Body *string `json:"body,omitempty"` // Labels is a pointer because `[]` is a statement — it clears every label // on the issue — while a caller that has not resolved label ids at all has // no business making it. A plain slice with omitempty cannot say both. Labels *[]int64 `json:"labels,omitempty"` Assignees *[]string `json:"assignees,omitempty"` // Milestone is a pointer for the same reason, and because 0 is Gitea's // "detach from its milestone" — a value somebody may well mean. Milestone *int64 `json:"milestone,omitempty"` State *string `json:"state,omitempty"` Ref *string `json:"ref,omitempty"` } // LabelRequest is the body of a label create or edit — everything a repository // needs to make one label. // // Value fields, not pointers, and every one of them is sent: Gitea 1.26 patches // only what it is given, but an older server reads an absent field as empty and // blanks it. A label edit is rare enough that sending the unchanged name and // description along costs nothing and removes a way to lose them. // // It goes up as a request body of its own because `tea labels create` could not // set `exclusive` — the flag that makes `type/*` behave like a single choice — // which is the whole reason label creation went through the API rather than a // CLI wrapper. // // What a label MEANS — which namespaces are exclusive, what colour a severity // is — is not decided here. This is the shape; the taxonomy is the domain's and // the palette is the bridge's. type LabelRequest struct { Name string `json:"name"` Color string `json:"color"` Description string `json:"description"` Exclusive bool `json:"exclusive"` } // Set is a pointer to v, for filling the optional fields of a request. Gitea // reads an absent key as "no opinion" and a present one as "make it this", so // those fields are pointers and this is the shorthand that fills them. func Set[T any](v T) *T { return &v }