File: issue_edit.go

package info (click to toggle)
tea-cli 0.11.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,648 kB
  • sloc: makefile: 116; sh: 17
file content (134 lines) | stat: -rw-r--r-- 3,844 bytes parent folder | download
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
}