summaryrefslogtreecommitdiffstats
path: root/vendor/code.gitea.io/sdk/gitea/release.go
blob: c8e7681d02c0b8dd61cfa81c3da04af335423e5a (plain)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package gitea

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"
)

// Release represents a repository release
type Release struct {
	ID           int64         `json:"id"`
	TagName      string        `json:"tag_name"`
	Target       string        `json:"target_commitish"`
	Title        string        `json:"name"`
	Note         string        `json:"body"`
	URL          string        `json:"url"`
	HTMLURL      string        `json:"html_url"`
	TarURL       string        `json:"tarball_url"`
	ZipURL       string        `json:"zipball_url"`
	IsDraft      bool          `json:"draft"`
	IsPrerelease bool          `json:"prerelease"`
	CreatedAt    time.Time     `json:"created_at"`
	PublishedAt  time.Time     `json:"published_at"`
	Publisher    *User         `json:"author"`
	Attachments  []*Attachment `json:"assets"`
}

// ListReleasesOptions options for listing repository's releases
type ListReleasesOptions struct {
	ListOptions
	IsDraft      *bool
	IsPreRelease *bool
}

// QueryEncode turns options into querystring argument
func (opt *ListReleasesOptions) QueryEncode() string {
	query := opt.getURLQuery()

	if opt.IsDraft != nil {
		query.Add("draft", fmt.Sprintf("%t", *opt.IsDraft))
	}
	if opt.IsPreRelease != nil {
		query.Add("draft", fmt.Sprintf("%t", *opt.IsPreRelease))
	}

	return query.Encode()
}

// ListReleases list releases of a repository
func (c *Client) ListReleases(owner, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
		return nil, nil, err
	}
	opt.setDefaults()
	releases := make([]*Release, 0, opt.PageSize)
	resp, err := c.getParsedResponse("GET",
		fmt.Sprintf("/repos/%s/%s/releases?%s", owner, repo, opt.QueryEncode()),
		nil, nil, &releases)
	return releases, resp, err
}

// GetRelease get a release of a repository by id
func (c *Client) GetRelease(owner, repo string, id int64) (*Release, *Response, error) {
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
		return nil, nil, err
	}
	r := new(Release)
	resp, err := c.getParsedResponse("GET",
		fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
		jsonHeader, nil, &r)
	return r, resp, err
}

// GetReleaseByTag get a release of a repository by tag
func (c *Client) GetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
	if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
		return c.fallbackGetReleaseByTag(owner, repo, tag)
	}
	if err := escapeValidatePathSegments(&owner, &repo, &tag); err != nil {
		return nil, nil, err
	}
	r := new(Release)
	resp, err := c.getParsedResponse("GET",
		fmt.Sprintf("/repos/%s/%s/releases/tags/%s", owner, repo, tag),
		nil, nil, &r)
	return r, resp, err
}

// CreateReleaseOption options when creating a release
type CreateReleaseOption struct {
	TagName      string `json:"tag_name"`
	Target       string `json:"target_commitish"`
	Title        string `json:"name"`
	Note         string `json:"body"`
	IsDraft      bool   `json:"draft"`
	IsPrerelease bool   `json:"prerelease"`
}

// Validate the CreateReleaseOption struct
func (opt CreateReleaseOption) Validate() error {
	if len(strings.TrimSpace(opt.Title)) == 0 {
		return fmt.Errorf("title is empty")
	}
	return nil
}

// CreateRelease create a release
func (c *Client) CreateRelease(owner, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
		return nil, nil, err
	}
	if err := opt.Validate(); err != nil {
		return nil, nil, err
	}
	body, err := json.Marshal(opt)
	if err != nil {
		return nil, nil, err
	}
	r := new(Release)
	resp, err := c.getParsedResponse("POST",
		fmt.Sprintf("/repos/%s/%s/releases", owner, repo),
		jsonHeader, bytes.NewReader(body), r)
	return r, resp, err
}

// EditReleaseOption options when editing a release
type EditReleaseOption struct {
	TagName      string `json:"tag_name"`
	Target       string `json:"target_commitish"`
	Title        string `json:"name"`
	Note         string `json:"body"`
	IsDraft      *bool  `json:"draft"`
	IsPrerelease *bool  `json:"prerelease"`
}

// EditRelease edit a release
func (c *Client) EditRelease(owner, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
	if err := escapeValidatePathSegments(&owner, &repo); err != nil {
		return nil, nil, err
	}
	body, err := json.Marshal(form)
	if err != nil {
		return nil, nil, err
	}
	r := new(Release)
	resp, err := c.getParsedResponse("PATCH",
		fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
		jsonHeader, bytes.NewReader(body), r)
	return r, resp, err
}

// DeleteRelease delete a release from a repository, keeping its tag
func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) {
	if err := escapeValidatePathSegments(&user, &repo); err != nil {
		return nil, err
	}
	_, resp, err := c.getResponse("DELETE",
		fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
		nil, nil)
	return resp, err
}

// DeleteReleaseByTag deletes a release frm a repository by tag
func (c *Client) DeleteReleaseByTag(user, repo string, tag string) (*Response, error) {
	if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
		return nil, err
	}
	if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
		return nil, err
	}
	_, resp, err := c.getResponse("DELETE",
		fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag),
		nil, nil)
	return resp, err
}

// fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 )
func (c *Client) fallbackGetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
	for i := 1; ; i++ {
		rl, resp, err := c.ListReleases(owner, repo, ListReleasesOptions{ListOptions: ListOptions{Page: i}})
		if err != nil {
			return nil, resp, err
		}
		if len(rl) == 0 {
			return nil,
				&Response{&http.Response{StatusCode: 404}},
				fmt.Errorf("release with tag '%s' not found", tag)
		}
		for _, r := range rl {
			if r.TagName == tag {
				return r, resp, nil
			}
		}
	}
}