1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package task
import (
"fmt"
"time"
"code.gitea.io/sdk/gitea"
"code.gitea.io/tea/modules/context"
)
// EditIssueOption wraps around gitea.EditIssueOption which has bad & incosistent semantics.
type EditIssueOption struct {
Index int64
Title *string
Body *string
Ref *string
Milestone *string
Deadline *time.Time
AddLabels []string
RemoveLabels []string
AddAssignees []string
// RemoveAssignees []string // NOTE: with the current go-sdk, clearing assignees is not possible.
}
// Normalizes the options into parameters that can be passed to the sdk.
// the returned value will be nil, when no change to this part of the issue is requested.
func (o EditIssueOption) toSdkOptions(ctx *context.TeaContext, client *gitea.Client) (*gitea.EditIssueOption, *gitea.IssueLabelsOption, *gitea.IssueLabelsOption, error) {
// labels have a separate API call, so they get their own options.
var addLabelOpts, rmLabelOpts *gitea.IssueLabelsOption
if o.AddLabels != nil && len(o.AddLabels) != 0 {
ids, err := ResolveLabelNames(client, ctx.Owner, ctx.Repo, o.AddLabels)
if err != nil {
return nil, nil, nil, err
}
addLabelOpts = &gitea.IssueLabelsOption{Labels: ids}
}
if o.RemoveLabels != nil && len(o.RemoveLabels) != 0 {
ids, err := ResolveLabelNames(client, ctx.Owner, ctx.Repo, o.RemoveLabels)
if err != nil {
return nil, nil, nil, err
}
rmLabelOpts = &gitea.IssueLabelsOption{Labels: ids}
}
issueOpts := gitea.EditIssueOption{}
var issueOptsDirty bool
if o.Title != nil {
issueOpts.Title = *o.Title
issueOptsDirty = true
}
if o.Body != nil {
issueOpts.Body = o.Body
issueOptsDirty = true
}
if o.Ref != nil {
issueOpts.Ref = o.Ref
issueOptsDirty = true
}
if o.Milestone != nil {
if *o.Milestone == "" {
issueOpts.Milestone = gitea.OptionalInt64(0)
} else {
ms, _, err := client.GetMilestoneByName(ctx.Owner, ctx.Repo, *o.Milestone)
if err != nil {
return nil, nil, nil, fmt.Errorf("Milestone '%s' not found", *o.Milestone)
}
issueOpts.Milestone = &ms.ID
}
issueOptsDirty = true
}
if o.Deadline != nil {
issueOpts.Deadline = o.Deadline
issueOptsDirty = true
if o.Deadline.IsZero() {
issueOpts.RemoveDeadline = gitea.OptionalBool(true)
}
}
if o.AddAssignees != nil && len(o.AddAssignees) != 0 {
issueOpts.Assignees = o.AddAssignees
issueOptsDirty = true
}
if issueOptsDirty {
return &issueOpts, addLabelOpts, rmLabelOpts, nil
}
return nil, addLabelOpts, rmLabelOpts, nil
}
// EditIssue edits an issue and returns the updated issue.
func EditIssue(ctx *context.TeaContext, client *gitea.Client, opts EditIssueOption) (*gitea.Issue, error) {
if client == nil {
client = ctx.Login.Client()
}
issueOpts, addLabelOpts, rmLabelOpts, err := opts.toSdkOptions(ctx, client)
if err != nil {
return nil, err
}
if rmLabelOpts != nil {
// NOTE: as of 1.17, there is no API to remove multiple labels at once.
for _, id := range rmLabelOpts.Labels {
_, err := client.DeleteIssueLabel(ctx.Owner, ctx.Repo, opts.Index, id)
if err != nil {
return nil, fmt.Errorf("could not remove labels: %s", err)
}
}
}
if addLabelOpts != nil {
_, _, err := client.AddIssueLabels(ctx.Owner, ctx.Repo, opts.Index, *addLabelOpts)
if err != nil {
return nil, fmt.Errorf("could not add labels: %s", err)
}
}
var issue *gitea.Issue
if issueOpts != nil {
issue, _, err = client.EditIssue(ctx.Owner, ctx.Repo, opts.Index, *issueOpts)
if err != nil {
return nil, fmt.Errorf("could not edit issue: %s", err)
}
} else {
issue, _, err = client.GetIssue(ctx.Owner, ctx.Repo, opts.Index)
if err != nil {
return nil, fmt.Errorf("could not get issue: %s", err)
}
}
return issue, nil
}
|