Skip to content

Commit 697af74

Browse files
committed
Release API endpoints
1 parent dc50c78 commit 697af74

File tree

6 files changed

+357
-4
lines changed

6 files changed

+357
-4
lines changed

models/release.go

+60
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ import (
1515
"code.gitea.io/git"
1616

1717
"code.gitea.io/gitea/modules/process"
18+
"code.gitea.io/gitea/modules/setting"
19+
20+
api "code.gitea.io/sdk/gitea"
1821
)
1922

2023
// Release represents a release of repository.
2124
type Release struct {
2225
ID int64 `xorm:"pk autoincr"`
2326
RepoID int64
27+
Repo *Repository `xorm:"-"`
2428
PublisherID int64
2529
Publisher *User `xorm:"-"`
2630
TagName string
@@ -53,6 +57,62 @@ func (r *Release) AfterSet(colName string, _ xorm.Cell) {
5357
}
5458
}
5559

60+
func (r *Release) loadAttributes(e Engine) error {
61+
var err error
62+
if r.Repo == nil {
63+
r.Repo, err = GetRepositoryByID(r.RepoID)
64+
if err != nil {
65+
return err
66+
}
67+
}
68+
if r.Publisher == nil {
69+
r.Publisher, err = GetUserByID(r.PublisherID)
70+
if err != nil {
71+
return err
72+
}
73+
}
74+
return nil
75+
}
76+
77+
// LoadAttributes load repo and publisher attributes for a realease
78+
func (r *Release) LoadAttributes() error {
79+
return r.loadAttributes(x)
80+
}
81+
82+
// APIURL the api url for a release. release must have attributes loaded
83+
func (r *Release) APIURL() string {
84+
return fmt.Sprintf("%sapi/v1/%s/releases/%d",
85+
setting.AppURL, r.Repo.FullName(), r.ID)
86+
}
87+
88+
// ZipURL the zip url for a release. release must have attributes loaded
89+
func (r *Release) ZipURL() string {
90+
return fmt.Sprintf("%s/archive/%s.zip", r.Repo.HTMLURL(), r.TagName)
91+
}
92+
93+
// TarURL the tar.gz url for a release. release must have attributes loaded
94+
func (r *Release) TarURL() string {
95+
return fmt.Sprintf("%s/archive/%s.tar.gz", r.Repo.HTMLURL(), r.TagName)
96+
}
97+
98+
// APIFormat convert a Release to api.Release
99+
func (r *Release) APIFormat() *api.Release {
100+
return &api.Release{
101+
ID: r.ID,
102+
TagName: r.TagName,
103+
Target: r.Target,
104+
Note: r.Note,
105+
URL: r.APIURL(),
106+
TarURL: r.TarURL(),
107+
ZipURL: r.ZipURL(),
108+
IsDraft: r.IsDraft,
109+
IsPrerelease: r.IsPrerelease,
110+
CreatedAt: r.Created,
111+
PublishedAt: r.Created,
112+
Publisher: r.Publisher.APIFormat(),
113+
}
114+
}
115+
56116
// IsReleaseExist returns true if release with given tag name already exists.
57117
func IsReleaseExist(repoID int64, tagName string) (bool, error) {
58118
if len(tagName) == 0 {

routers/api/v1/api.go

+7
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,13 @@ func RegisterRoutes(m *macaron.Macaron) {
331331
m.Put("", user.Watch)
332332
m.Delete("", user.Unwatch)
333333
})
334+
m.Group("/releases", func() {
335+
m.Combo("").Get(repo.ListReleases).
336+
Post(bind(api.CreateReleaseOption{}), repo.CreateRelease)
337+
m.Combo("/:id").Get(repo.GetRelease).
338+
Patch(bind(api.EditReleaseOption{}), repo.EditRelease).
339+
Delete(repo.DeleteRelease)
340+
})
334341
m.Get("/editorconfig/:filename", context.RepoRef(), repo.GetEditorconfig)
335342
m.Group("/pulls", func() {
336343
m.Combo("").Get(bind(api.ListPullRequestsOptions{}), repo.ListPullRequests).Post(reqRepoWriter(), bind(api.CreatePullRequestOption{}), repo.CreatePullRequest)

routers/api/v1/repo/release.go

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// Copyright 2016 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package repo
6+
7+
import (
8+
"strings"
9+
10+
api "code.gitea.io/sdk/gitea"
11+
12+
"code.gitea.io/gitea/models"
13+
"code.gitea.io/gitea/modules/context"
14+
)
15+
16+
// GetRelease get a single release of a repository
17+
func GetRelease(ctx *context.APIContext) {
18+
id := ctx.ParamsInt64(":id")
19+
release, err := models.GetReleaseByID(id)
20+
if err != nil {
21+
ctx.Error(500, "GetReleaseByID", err)
22+
return
23+
}
24+
if release.RepoID != ctx.Repo.Repository.ID {
25+
ctx.Status(404)
26+
return
27+
}
28+
if err := release.LoadAttributes(); err != nil {
29+
ctx.Error(500, "LoadAttributes", err)
30+
return
31+
}
32+
ctx.JSON(200, release.APIFormat())
33+
}
34+
35+
// ListReleases list a repository's releases
36+
func ListReleases(ctx *context.APIContext) {
37+
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, 1, 2147483647)
38+
if err != nil {
39+
ctx.Error(500, "GetReleasesByRepoID", err)
40+
return
41+
}
42+
rels := make([]*api.Release, len(releases))
43+
access, err := models.AccessLevel(ctx.User, ctx.Repo.Repository)
44+
if err != nil {
45+
ctx.Error(500, "AccessLevel", err)
46+
return
47+
}
48+
for i, release := range releases {
49+
if release.IsDraft && access < models.AccessModeWrite {
50+
// hide drafts from users without push access
51+
continue
52+
}
53+
if err := release.LoadAttributes(); err != nil {
54+
ctx.Error(500, "LoadAttributes", err)
55+
return
56+
}
57+
rels[i] = release.APIFormat()
58+
}
59+
ctx.JSON(200, rels)
60+
}
61+
62+
// CreateRelease create a release
63+
func CreateRelease(ctx *context.APIContext, form api.CreateReleaseOption) {
64+
if ctx.Repo.AccessMode < models.AccessModeWrite {
65+
ctx.Status(403)
66+
return
67+
}
68+
if !ctx.Repo.GitRepo.IsTagExist(form.TagName) {
69+
ctx.Status(404)
70+
return
71+
}
72+
tag, err := ctx.Repo.GitRepo.GetTag(form.TagName)
73+
if err != nil {
74+
ctx.Error(500, "GetTag", err)
75+
return
76+
}
77+
commit, err := tag.Commit()
78+
if err != nil {
79+
ctx.Error(500, "Commit", err)
80+
return
81+
}
82+
commitsCount, err := commit.CommitsCount()
83+
if err != nil {
84+
ctx.Error(500, "CommitsCount", err)
85+
return
86+
}
87+
rel := &models.Release{
88+
RepoID: ctx.Repo.Repository.ID,
89+
PublisherID: ctx.User.ID,
90+
Publisher: ctx.User,
91+
TagName: form.TagName,
92+
LowerTagName: strings.ToLower(form.TagName),
93+
Target: form.Target,
94+
Title: form.Title,
95+
Sha1: commit.ID.String(),
96+
NumCommits: commitsCount,
97+
Note: form.Note,
98+
IsDraft: form.IsDraft,
99+
IsPrerelease: form.IsPrerelease,
100+
CreatedUnix: commit.Author.When.Unix(),
101+
}
102+
if err := models.CreateRelease(ctx.Repo.GitRepo, rel); err != nil {
103+
if models.IsErrReleaseAlreadyExist(err) {
104+
ctx.Status(409)
105+
} else {
106+
ctx.Error(500, "CreateRelease", err)
107+
}
108+
return
109+
}
110+
ctx.JSON(201, rel.APIFormat())
111+
}
112+
113+
// EditRelease edit a release
114+
func EditRelease(ctx *context.APIContext, form api.EditReleaseOption) {
115+
if ctx.Repo.AccessMode < models.AccessModeWrite {
116+
ctx.Status(403)
117+
return
118+
}
119+
id := ctx.ParamsInt64(":id")
120+
rel, err := models.GetReleaseByID(id)
121+
if err != nil {
122+
ctx.Error(500, "GetReleaseByID", err)
123+
return
124+
}
125+
if rel.RepoID != ctx.Repo.Repository.ID {
126+
ctx.Status(404)
127+
return
128+
}
129+
130+
if len(form.TagName) > 0 {
131+
rel.TagName = form.TagName
132+
}
133+
if len(form.Target) > 0 {
134+
rel.Target = form.Target
135+
}
136+
if len(form.Title) > 0 {
137+
rel.Title = form.Title
138+
}
139+
if len(form.Note) > 0 {
140+
rel.Note = form.Note
141+
}
142+
if form.IsDraft != nil {
143+
rel.IsDraft = *form.IsDraft
144+
}
145+
if form.IsPrerelease != nil {
146+
rel.IsPrerelease = *form.IsPrerelease
147+
}
148+
if err := models.UpdateRelease(ctx.Repo.GitRepo, rel); err != nil {
149+
ctx.Error(500, "UpdateRelease", err)
150+
return
151+
}
152+
153+
rel, err = models.GetReleaseByID(id)
154+
if err != nil {
155+
ctx.Error(500, "GetReleaseByID", err)
156+
return
157+
}
158+
if err := rel.LoadAttributes(); err != nil {
159+
ctx.Error(500, "LoadAttributes", err)
160+
return
161+
}
162+
ctx.JSON(200, rel.APIFormat())
163+
}
164+
165+
// DeleteRelease delete a release from a repository
166+
func DeleteRelease(ctx *context.APIContext) {
167+
if ctx.Repo.AccessMode < models.AccessModeWrite {
168+
ctx.Status(403)
169+
return
170+
}
171+
id := ctx.ParamsInt64(":id")
172+
release, err := models.GetReleaseByID(id)
173+
if err != nil {
174+
ctx.Error(500, "GetReleaseByID", err)
175+
return
176+
}
177+
if release.RepoID != ctx.Repo.Repository.ID {
178+
ctx.Status(404)
179+
return
180+
}
181+
if err := models.DeleteReleaseByID(id, ctx.User); err != nil {
182+
ctx.Error(500, "DeleteReleaseByID", err)
183+
return
184+
}
185+
ctx.Status(204)
186+
}

vendor/code.gitea.io/sdk/gitea/hook.go

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/code.gitea.io/sdk/gitea/releases.go

+101
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)