* Add Attachment API * repos/:owner/:repo/releases (add attachments) * repos/:owner/:repo/releases/:id (add attachments) * repos/:owner/:repo/releases/:id/attachments * repos/:owner/:repo/releases/:id/attachments/:attachment_id Signed-off-by: Jonas Franz <info@jonasfranz.de> * Add unit tests for new attachment functions Fix comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * fix lint * Update vendor.json Signed-off-by: Jonas Franz <info@jonasfranz.software> * remove version of sdk Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix unit tests Add missing license header Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add CreateReleaseAttachment Add EditReleaseAttachment Add DeleteReleaseAttachment Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add filename query parameter for choosing another name for an attachment Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix order of imports Signed-off-by: Jonas Franz <info@jonasfranz.software> * Restricting updatable attachment columns Signed-off-by: Jonas Franz <info@jonasfranz.software> * gofmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update go-sdk Replace Attachments with Assets Signed-off-by: Jonas Franz <info@jonasfranz.de> * Update go-sdk Signed-off-by: Jonas Franz <info@jonasfranz.de> * Updating go-sdk and regenerating swagger Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add missing file of go-sdk Signed-off-by: Jonas Franz <info@jonasfranz.software> * Change origin of code.gitea.io/sdk to code.gitea.io/sdk Update code.gitea.io/sdk Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update swagger Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update updateAttachmenttags/v1.5.0-dev
@@ -11,10 +11,12 @@ import ( | |||
"os" | |||
"path" | |||
gouuid "github.com/satori/go.uuid" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/util" | |||
api "code.gitea.io/sdk/gitea" | |||
"github.com/go-xorm/xorm" | |||
gouuid "github.com/satori/go.uuid" | |||
) | |||
// Attachment represent a attachment of issue/comment/release. | |||
@@ -39,6 +41,20 @@ func (a *Attachment) IncreaseDownloadCount() error { | |||
return nil | |||
} | |||
// APIFormat converts models.Attachment to api.Attachment | |||
func (a *Attachment) APIFormat() *api.Attachment { | |||
size, _ := a.Size() | |||
return &api.Attachment{ | |||
ID: a.ID, | |||
Name: a.Name, | |||
Created: a.CreatedUnix.AsTime(), | |||
DownloadCount: a.DownloadCount, | |||
Size: size, | |||
UUID: a.UUID, | |||
DownloadURL: a.DownloadURL(), | |||
} | |||
} | |||
// AttachmentLocalPath returns where attachment is stored in local file | |||
// system based on given UUID. | |||
func AttachmentLocalPath(uuid string) string { | |||
@@ -50,6 +66,20 @@ func (a *Attachment) LocalPath() string { | |||
return AttachmentLocalPath(a.UUID) | |||
} | |||
// Size returns the file's size of the attachment | |||
func (a *Attachment) Size() (int64, error) { | |||
fi, err := os.Stat(a.LocalPath()) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return fi.Size(), nil | |||
} | |||
// DownloadURL returns the download url of the attached file | |||
func (a *Attachment) DownloadURL() string { | |||
return fmt.Sprintf("%sattachments/%s", setting.AppURL, a.UUID) | |||
} | |||
// NewAttachment creates a new attachment object. | |||
func NewAttachment(name string, buf []byte, file multipart.File) (_ *Attachment, err error) { | |||
attach := &Attachment{ | |||
@@ -81,6 +111,22 @@ func NewAttachment(name string, buf []byte, file multipart.File) (_ *Attachment, | |||
return attach, nil | |||
} | |||
// GetAttachmentByID returns attachment by given id | |||
func GetAttachmentByID(id int64) (*Attachment, error) { | |||
return getAttachmentByID(x, id) | |||
} | |||
func getAttachmentByID(e Engine, id int64) (*Attachment, error) { | |||
attach := &Attachment{ID: id} | |||
if has, err := e.Get(attach); err != nil { | |||
return nil, err | |||
} else if !has { | |||
return nil, ErrAttachmentNotExist{ID: id, UUID: ""} | |||
} | |||
return attach, nil | |||
} | |||
func getAttachmentByUUID(e Engine, uuid string) (*Attachment, error) { | |||
attach := &Attachment{UUID: uuid} | |||
has, err := e.Get(attach) | |||
@@ -180,3 +226,20 @@ func DeleteAttachmentsByComment(commentID int64, remove bool) (int, error) { | |||
return DeleteAttachments(attachments, remove) | |||
} | |||
// UpdateAttachment updates the given attachment in database | |||
func UpdateAttachment(atta *Attachment) error { | |||
return updateAttachment(x, atta) | |||
} | |||
func updateAttachment(e Engine, atta *Attachment) error { | |||
var sess *xorm.Session | |||
if atta.ID != 0 && atta.UUID == "" { | |||
sess = e.ID(atta.ID) | |||
} else { | |||
// Use uuid only if id is not set and uuid is set | |||
sess = e.Where("uuid = ?", atta.UUID) | |||
} | |||
_, err := sess.Cols("name", "issue_id", "release_id", "comment_id", "download_count").Update(atta) | |||
return err | |||
} |
@@ -58,3 +58,32 @@ func TestDeleteAttachments(t *testing.T) { | |||
assert.True(t, IsErrAttachmentNotExist(err)) | |||
assert.Nil(t, attachment) | |||
} | |||
func TestGetAttachmentByID(t *testing.T) { | |||
assert.NoError(t, PrepareTestDatabase()) | |||
attach, err := GetAttachmentByID(1) | |||
assert.NoError(t, err) | |||
assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attach.UUID) | |||
} | |||
func TestAttachment_DownloadURL(t *testing.T) { | |||
attach := &Attachment{ | |||
UUID: "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", | |||
ID: 1, | |||
} | |||
assert.Equal(t, "https://try.gitea.io/attachments/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attach.DownloadURL()) | |||
} | |||
func TestUpdateAttachment(t *testing.T) { | |||
assert.NoError(t, PrepareTestDatabase()) | |||
attach, err := GetAttachmentByID(1) | |||
assert.NoError(t, err) | |||
assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attach.UUID) | |||
attach.Name = "new_name" | |||
assert.NoError(t, UpdateAttachment(attach)) | |||
AssertExistsAndLoadBean(t, &Attachment{Name: "new_name"}) | |||
} |
@@ -53,7 +53,7 @@ func (r *Release) loadAttributes(e Engine) error { | |||
return err | |||
} | |||
} | |||
return nil | |||
return GetReleaseAttachments(r) | |||
} | |||
// LoadAttributes load repo and publisher attributes for a release | |||
@@ -79,6 +79,10 @@ func (r *Release) TarURL() string { | |||
// APIFormat convert a Release to api.Release | |||
func (r *Release) APIFormat() *api.Release { | |||
assets := make([]*api.Attachment, 0) | |||
for _, att := range r.Attachments { | |||
assets = append(assets, att.APIFormat()) | |||
} | |||
return &api.Release{ | |||
ID: r.ID, | |||
TagName: r.TagName, | |||
@@ -92,6 +96,7 @@ func (r *Release) APIFormat() *api.Release { | |||
CreatedAt: r.CreatedUnix.AsTime(), | |||
PublishedAt: r.CreatedUnix.AsTime(), | |||
Publisher: r.Publisher.APIFormat(), | |||
Attachments: assets, | |||
} | |||
} | |||
@@ -4,4 +4,4 @@ | |||
"less": "^2.7.2", | |||
"less-plugin-clean-css": "^1.5.1" | |||
} | |||
} | |||
} |
@@ -3225,6 +3225,37 @@ | |||
}, | |||
"/repos/{owner}/{repo}/releases": { | |||
"get": { | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"repository" | |||
], | |||
"summary": "List a repo's releases", | |||
"operationId": "repoListReleases", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
} | |||
], | |||
"responses": { | |||
"200": { | |||
"$ref": "#/responses/ReleaseList" | |||
} | |||
} | |||
}, | |||
"post": { | |||
"consumes": [ | |||
"application/json" | |||
], | |||
@@ -3267,6 +3298,44 @@ | |||
} | |||
}, | |||
"/repos/{owner}/{repo}/releases/{id}": { | |||
"get": { | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"repository" | |||
], | |||
"summary": "Get a release", | |||
"operationId": "repoGetRelease", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the release to get", | |||
"name": "id", | |||
"in": "path", | |||
"required": true | |||
} | |||
], | |||
"responses": { | |||
"200": { | |||
"$ref": "#/responses/Release" | |||
} | |||
} | |||
}, | |||
"delete": { | |||
"tags": [ | |||
"repository" | |||
@@ -3351,6 +3420,247 @@ | |||
} | |||
} | |||
}, | |||
"/repos/{owner}/{repo}/releases/{id}/assets": { | |||
"get": { | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"repository" | |||
], | |||
"summary": "List release's attachments", | |||
"operationId": "repoListReleaseAttachments", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the release", | |||
"name": "id", | |||
"in": "path", | |||
"required": true | |||
} | |||
], | |||
"responses": { | |||
"200": { | |||
"$ref": "#/responses/AttachmentList" | |||
} | |||
} | |||
}, | |||
"post": { | |||
"consumes": [ | |||
"multipart/form-data" | |||
], | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"repository" | |||
], | |||
"summary": "Create a release attachment", | |||
"operationId": "repoCreateReleaseAttachment", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the release", | |||
"name": "id", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the attachment", | |||
"name": "name", | |||
"in": "query" | |||
}, | |||
{ | |||
"type": "file", | |||
"description": "attachment to upload", | |||
"name": "attachment", | |||
"in": "formData", | |||
"required": true | |||
} | |||
], | |||
"responses": { | |||
"201": { | |||
"$ref": "#/responses/Attachment" | |||
} | |||
} | |||
} | |||
}, | |||
"/repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}": { | |||
"get": { | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"repository" | |||
], | |||
"summary": "Get a release attachment", | |||
"operationId": "repoGetReleaseAttachment", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the release", | |||
"name": "id", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the attachment to get", | |||
"name": "attachment_id", | |||
"in": "path", | |||
"required": true | |||
} | |||
], | |||
"responses": { | |||
"200": { | |||
"$ref": "#/responses/Attachment" | |||
} | |||
} | |||
}, | |||
"delete": { | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"repository" | |||
], | |||
"summary": "Delete a release attachment", | |||
"operationId": "repoDeleteReleaseAttachment", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the release", | |||
"name": "id", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the attachment to delete", | |||
"name": "attachment_id", | |||
"in": "path", | |||
"required": true | |||
} | |||
], | |||
"responses": { | |||
"204": { | |||
"$ref": "#/responses/empty" | |||
} | |||
} | |||
}, | |||
"patch": { | |||
"consumes": [ | |||
"application/json" | |||
], | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"repository" | |||
], | |||
"summary": "Edit a release attachment", | |||
"operationId": "repoEditReleaseAttachment", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the release", | |||
"name": "id", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "integer", | |||
"description": "id of the attachment to edit", | |||
"name": "attachment_id", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"name": "body", | |||
"in": "body", | |||
"schema": { | |||
"$ref": "#/definitions/EditAttachmentOptions" | |||
} | |||
} | |||
], | |||
"responses": { | |||
"201": { | |||
"$ref": "#/responses/Attachment" | |||
} | |||
} | |||
} | |||
}, | |||
"/repos/{owner}/{repo}/stargazers": { | |||
"get": { | |||
"produces": [ | |||
@@ -4994,6 +5304,45 @@ | |||
}, | |||
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" | |||
}, | |||
"Attachment": { | |||
"description": "Attachment a generic attachment", | |||
"type": "object", | |||
"properties": { | |||
"browser_download_url": { | |||
"type": "string", | |||
"x-go-name": "DownloadURL" | |||
}, | |||
"created_at": { | |||
"type": "string", | |||
"format": "date-time", | |||
"x-go-name": "Created" | |||
}, | |||
"download_count": { | |||
"type": "integer", | |||
"format": "int64", | |||
"x-go-name": "DownloadCount" | |||
}, | |||
"id": { | |||
"type": "integer", | |||
"format": "int64", | |||
"x-go-name": "ID" | |||
}, | |||
"name": { | |||
"type": "string", | |||
"x-go-name": "Name" | |||
}, | |||
"size": { | |||
"type": "integer", | |||
"format": "int64", | |||
"x-go-name": "Size" | |||
}, | |||
"uuid": { | |||
"type": "string", | |||
"x-go-name": "UUID" | |||
} | |||
}, | |||
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" | |||
}, | |||
"Branch": { | |||
"description": "Branch represents a repository branch", | |||
"type": "object", | |||
@@ -5202,6 +5551,11 @@ | |||
"uniqueItems": true, | |||
"x-go-name": "Key" | |||
}, | |||
"read_only": { | |||
"description": "Describe if the key has only read access or read/write", | |||
"type": "boolean", | |||
"x-go-name": "ReadOnly" | |||
}, | |||
"title": { | |||
"description": "Title of the key to add", | |||
"type": "string", | |||
@@ -5540,6 +5894,17 @@ | |||
}, | |||
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" | |||
}, | |||
"EditAttachmentOptions": { | |||
"description": "EditAttachmentOptions options for editing attachments", | |||
"type": "object", | |||
"properties": { | |||
"name": { | |||
"type": "string", | |||
"x-go-name": "Name" | |||
} | |||
}, | |||
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea" | |||
}, | |||
"EditHookOption": { | |||
"description": "EditHookOption options when modify one hook", | |||
"type": "object", | |||
@@ -6459,6 +6824,13 @@ | |||
"description": "Release represents a repository release", | |||
"type": "object", | |||
"properties": { | |||
"assets": { | |||
"type": "array", | |||
"items": { | |||
"$ref": "#/definitions/Attachment" | |||
}, | |||
"x-go-name": "Attachments" | |||
}, | |||
"author": { | |||
"$ref": "#/definitions/User" | |||
}, | |||
@@ -6848,6 +7220,19 @@ | |||
"AccessTokenList": { | |||
"description": "AccessTokenList represents a list of API access token." | |||
}, | |||
"Attachment": { | |||
"schema": { | |||
"$ref": "#/definitions/Attachment" | |||
} | |||
}, | |||
"AttachmentList": { | |||
"schema": { | |||
"type": "array", | |||
"items": { | |||
"$ref": "#/definitions/Attachment" | |||
} | |||
} | |||
}, | |||
"Branch": { | |||
"schema": { | |||
"$ref": "#/definitions/Branch" | |||
@@ -7131,7 +7516,7 @@ | |||
}, | |||
"parameterBodies": { | |||
"schema": { | |||
"$ref": "#/definitions/MigrateRepoForm" | |||
"$ref": "#/definitions/EditAttachmentOptions" | |||
}, | |||
"headers": { | |||
"AddCollaboratorOption": {}, | |||
@@ -7152,6 +7537,7 @@ | |||
"CreateTeamOption": {}, | |||
"CreateUserOption": {}, | |||
"DeleteEmailOption": {}, | |||
"EditAttachmentOptions": {}, | |||
"EditHookOption": {}, | |||
"EditIssueCommentOption": {}, | |||
"EditIssueOption": {}, |
@@ -469,9 +469,18 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Group("/releases", func() { | |||
m.Combo("").Get(repo.ListReleases). | |||
Post(reqToken(), reqRepoWriter(), context.ReferencesGitRepo(), bind(api.CreateReleaseOption{}), repo.CreateRelease) | |||
m.Combo("/:id").Get(repo.GetRelease). | |||
Patch(reqToken(), reqRepoWriter(), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease). | |||
Delete(reqToken(), reqRepoWriter(), repo.DeleteRelease) | |||
m.Group("/:id", func() { | |||
m.Combo("").Get(repo.GetRelease). | |||
Patch(reqToken(), reqRepoWriter(), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease). | |||
Delete(reqToken(), reqRepoWriter(), repo.DeleteRelease) | |||
m.Group("/assets", func() { | |||
m.Combo("").Get(repo.ListReleaseAttachments). | |||
Post(reqToken(), reqRepoWriter(), repo.CreateReleaseAttachment) | |||
m.Combo("/:asset").Get(repo.GetReleaseAttachment). | |||
Patch(reqToken(), reqRepoWriter(), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment). | |||
Delete(reqToken(), reqRepoWriter(), repo.DeleteReleaseAttachment) | |||
}) | |||
}) | |||
}) | |||
m.Post("/mirror-sync", reqToken(), reqRepoWriter(), repo.MirrorSync) | |||
m.Get("/editorconfig/:filename", context.RepoRef(), repo.GetEditorconfig) |
@@ -13,7 +13,7 @@ import ( | |||
// GetRelease get a single release of a repository | |||
func GetRelease(ctx *context.APIContext) { | |||
// swagger:operation GET /repos/{owner}/{repo}/releases repository repoGetRelease | |||
// swagger:operation GET /repos/{owner}/{repo}/releases/{id} repository repoGetRelease | |||
// --- | |||
// summary: Get a release | |||
// produces: | |||
@@ -29,7 +29,7 @@ func GetRelease(ctx *context.APIContext) { | |||
// description: name of the repo | |||
// type: string | |||
// required: true | |||
// - name: repo | |||
// - name: id | |||
// in: path | |||
// description: id of the release to get | |||
// type: integer |
@@ -0,0 +1,322 @@ | |||
// Copyright 2018 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 repo | |||
import ( | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/setting" | |||
api "code.gitea.io/sdk/gitea" | |||
"errors" | |||
"net/http" | |||
"strings" | |||
) | |||
// GetReleaseAttachment gets a single attachment of the release | |||
func GetReleaseAttachment(ctx *context.APIContext) { | |||
// swagger:operation GET /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} repository repoGetReleaseAttachment | |||
// --- | |||
// summary: Get a release attachment | |||
// produces: | |||
// - application/json | |||
// parameters: | |||
// - name: owner | |||
// in: path | |||
// description: owner of the repo | |||
// type: string | |||
// required: true | |||
// - name: repo | |||
// in: path | |||
// description: name of the repo | |||
// type: string | |||
// required: true | |||
// - name: id | |||
// in: path | |||
// description: id of the release | |||
// type: integer | |||
// required: true | |||
// - name: attachment_id | |||
// in: path | |||
// description: id of the attachment to get | |||
// type: integer | |||
// required: true | |||
// responses: | |||
// "200": | |||
// "$ref": "#/responses/Attachment" | |||
releaseID := ctx.ParamsInt64(":id") | |||
attachID := ctx.ParamsInt64(":asset") | |||
attach, err := models.GetAttachmentByID(attachID) | |||
if err != nil { | |||
ctx.Error(500, "GetAttachmentByID", err) | |||
return | |||
} | |||
if attach.ReleaseID != releaseID { | |||
ctx.Status(404) | |||
return | |||
} | |||
// FIXME Should prove the existence of the given repo, but results in unnecessary database requests | |||
ctx.JSON(200, attach.APIFormat()) | |||
} | |||
// ListReleaseAttachments lists all attachments of the release | |||
func ListReleaseAttachments(ctx *context.APIContext) { | |||
// swagger:operation GET /repos/{owner}/{repo}/releases/{id}/assets repository repoListReleaseAttachments | |||
// --- | |||
// summary: List release's attachments | |||
// produces: | |||
// - application/json | |||
// parameters: | |||
// - name: owner | |||
// in: path | |||
// description: owner of the repo | |||
// type: string | |||
// required: true | |||
// - name: repo | |||
// in: path | |||
// description: name of the repo | |||
// type: string | |||
// required: true | |||
// - name: id | |||
// in: path | |||
// description: id of the release | |||
// type: integer | |||
// required: true | |||
// responses: | |||
// "200": | |||
// "$ref": "#/responses/AttachmentList" | |||
releaseID := ctx.ParamsInt64(":id") | |||
release, err := models.GetReleaseByID(releaseID) | |||
if err != nil { | |||
ctx.Error(500, "GetReleaseByID", err) | |||
return | |||
} | |||
if release.RepoID != ctx.Repo.Repository.ID { | |||
ctx.Status(404) | |||
return | |||
} | |||
if err := release.LoadAttributes(); err != nil { | |||
ctx.Error(500, "LoadAttributes", err) | |||
return | |||
} | |||
ctx.JSON(200, release.APIFormat().Attachments) | |||
} | |||
// CreateReleaseAttachment creates an attachment and saves the given file | |||
func CreateReleaseAttachment(ctx *context.APIContext) { | |||
// swagger:operation POST /repos/{owner}/{repo}/releases/{id}/assets repository repoCreateReleaseAttachment | |||
// --- | |||
// summary: Create a release attachment | |||
// produces: | |||
// - application/json | |||
// consumes: | |||
// - multipart/form-data | |||
// parameters: | |||
// - name: owner | |||
// in: path | |||
// description: owner of the repo | |||
// type: string | |||
// required: true | |||
// - name: repo | |||
// in: path | |||
// description: name of the repo | |||
// type: string | |||
// required: true | |||
// - name: id | |||
// in: path | |||
// description: id of the release | |||
// type: integer | |||
// required: true | |||
// - name: name | |||
// in: query | |||
// description: name of the attachment | |||
// type: string | |||
// required: false | |||
// - name: attachment | |||
// in: formData | |||
// description: attachment to upload | |||
// type: file | |||
// required: true | |||
// responses: | |||
// "201": | |||
// "$ref": "#/responses/Attachment" | |||
// Check if attachments are enabled | |||
if !setting.AttachmentEnabled { | |||
ctx.Error(404, "AttachmentEnabled", errors.New("attachment is not enabled")) | |||
return | |||
} | |||
// Check if release exists an load release | |||
releaseID := ctx.ParamsInt64(":id") | |||
release, err := models.GetReleaseByID(releaseID) | |||
if err != nil { | |||
ctx.Error(500, "GetReleaseByID", err) | |||
return | |||
} | |||
// Get uploaded file from request | |||
file, header, err := ctx.GetFile("attachment") | |||
if err != nil { | |||
ctx.Error(500, "GetFile", err) | |||
return | |||
} | |||
defer file.Close() | |||
buf := make([]byte, 1024) | |||
n, _ := file.Read(buf) | |||
if n > 0 { | |||
buf = buf[:n] | |||
} | |||
// Check if the filetype is allowed by the settings | |||
fileType := http.DetectContentType(buf) | |||
allowedTypes := strings.Split(setting.AttachmentAllowedTypes, ",") | |||
allowed := false | |||
for _, t := range allowedTypes { | |||
t := strings.Trim(t, " ") | |||
if t == "*/*" || t == fileType { | |||
allowed = true | |||
break | |||
} | |||
} | |||
if !allowed { | |||
ctx.Error(400, "DetectContentType", errors.New("File type is not allowed")) | |||
return | |||
} | |||
var filename = header.Filename | |||
if query := ctx.Query("name"); query != "" { | |||
filename = query | |||
} | |||
// Create a new attachment and save the file | |||
attach, err := models.NewAttachment(filename, buf, file) | |||
if err != nil { | |||
ctx.Error(500, "NewAttachment", err) | |||
return | |||
} | |||
attach.ReleaseID = release.ID | |||
if err := models.UpdateAttachment(attach); err != nil { | |||
ctx.Error(500, "UpdateAttachment", err) | |||
return | |||
} | |||
ctx.JSON(201, attach.APIFormat()) | |||
} | |||
// EditReleaseAttachment updates the given attachment | |||
func EditReleaseAttachment(ctx *context.APIContext, form api.EditAttachmentOptions) { | |||
// swagger:operation PATCH /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} repository repoEditReleaseAttachment | |||
// --- | |||
// summary: Edit a release attachment | |||
// produces: | |||
// - application/json | |||
// consumes: | |||
// - application/json | |||
// parameters: | |||
// - name: owner | |||
// in: path | |||
// description: owner of the repo | |||
// type: string | |||
// required: true | |||
// - name: repo | |||
// in: path | |||
// description: name of the repo | |||
// type: string | |||
// required: true | |||
// - name: id | |||
// in: path | |||
// description: id of the release | |||
// type: integer | |||
// required: true | |||
// - name: attachment_id | |||
// in: path | |||
// description: id of the attachment to edit | |||
// type: integer | |||
// required: true | |||
// - name: body | |||
// in: body | |||
// schema: | |||
// "$ref": "#/definitions/EditAttachmentOptions" | |||
// responses: | |||
// "201": | |||
// "$ref": "#/responses/Attachment" | |||
// Check if release exists an load release | |||
releaseID := ctx.ParamsInt64(":id") | |||
attachID := ctx.ParamsInt64(":attachment") | |||
attach, err := models.GetAttachmentByID(attachID) | |||
if err != nil { | |||
ctx.Error(500, "GetAttachmentByID", err) | |||
return | |||
} | |||
if attach.ReleaseID != releaseID { | |||
ctx.Status(404) | |||
return | |||
} | |||
// FIXME Should prove the existence of the given repo, but results in unnecessary database requests | |||
if form.Name != "" { | |||
attach.Name = form.Name | |||
} | |||
if err := models.UpdateAttachment(attach); err != nil { | |||
ctx.Error(500, "UpdateAttachment", attach) | |||
} | |||
ctx.JSON(201, attach.APIFormat()) | |||
} | |||
// DeleteReleaseAttachment delete a given attachment | |||
func DeleteReleaseAttachment(ctx *context.APIContext) { | |||
// swagger:operation DELETE /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} repository repoDeleteReleaseAttachment | |||
// --- | |||
// summary: Delete a release attachment | |||
// produces: | |||
// - application/json | |||
// parameters: | |||
// - name: owner | |||
// in: path | |||
// description: owner of the repo | |||
// type: string | |||
// required: true | |||
// - name: repo | |||
// in: path | |||
// description: name of the repo | |||
// type: string | |||
// required: true | |||
// - name: id | |||
// in: path | |||
// description: id of the release | |||
// type: integer | |||
// required: true | |||
// - name: attachment_id | |||
// in: path | |||
// description: id of the attachment to delete | |||
// type: integer | |||
// required: true | |||
// responses: | |||
// "204": | |||
// "$ref": "#/responses/empty" | |||
// Check if release exists an load release | |||
releaseID := ctx.ParamsInt64(":id") | |||
attachID := ctx.ParamsInt64(":attachment") | |||
attach, err := models.GetAttachmentByID(attachID) | |||
if err != nil { | |||
ctx.Error(500, "GetAttachmentByID", err) | |||
return | |||
} | |||
if attach.ReleaseID != releaseID { | |||
ctx.Status(404) | |||
return | |||
} | |||
// FIXME Should prove the existence of the given repo, but results in unnecessary database requests | |||
if err := models.DeleteAttachment(attach, true); err != nil { | |||
ctx.Error(500, "DeleteAttachment", err) | |||
return | |||
} | |||
ctx.Status(204) | |||
} |
@@ -63,4 +63,6 @@ type swaggerParameterBodies struct { | |||
EditUserOption api.EditUserOption | |||
MigrateRepoForm auth.MigrateRepoForm | |||
EditAttachmentOptions api.EditAttachmentOptions | |||
} |
@@ -90,3 +90,15 @@ type swaggerResponseWatchInfo struct { | |||
type swaggerResponseSearchResults struct { | |||
Body api.SearchResults `json:"body"` | |||
} | |||
// swagger:response AttachmentList | |||
type swaggerResponseAttachmentList struct { | |||
//in: body | |||
Body []api.Attachment `json:"body"` | |||
} | |||
// swagger:response Attachment | |||
type swaggerResponseAttachment struct { | |||
//in: body | |||
Body api.Attachment `json:"body"` | |||
} |
@@ -12,7 +12,7 @@ import ( | |||
// CreateUserOption create user options | |||
type CreateUserOption struct { | |||
SourceID int64 `json:"source_id"` | |||
SourceID int64 `json:"source_id"` | |||
LoginName string `json:"login_name"` | |||
// required: true | |||
Username string `json:"username" binding:"Required;AlphaDashDot;MaxSize(35)"` | |||
@@ -21,8 +21,8 @@ type CreateUserOption struct { | |||
// swagger:strfmt email | |||
Email string `json:"email" binding:"Required;Email;MaxSize(254)"` | |||
// required: true | |||
Password string `json:"password" binding:"Required;MaxSize(255)"` | |||
SendNotify bool `json:"send_notify"` | |||
Password string `json:"password" binding:"Required;MaxSize(255)"` | |||
SendNotify bool `json:"send_notify"` | |||
} | |||
// AdminCreateUser create a user | |||
@@ -37,20 +37,20 @@ func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, error) { | |||
// EditUserOption edit user options | |||
type EditUserOption struct { | |||
SourceID int64 `json:"source_id"` | |||
SourceID int64 `json:"source_id"` | |||
LoginName string `json:"login_name"` | |||
FullName string `json:"full_name" binding:"MaxSize(100)"` | |||
FullName string `json:"full_name" binding:"MaxSize(100)"` | |||
// required: true | |||
// swagger:strfmt email | |||
Email string `json:"email" binding:"Required;Email;MaxSize(254)"` | |||
Password string `json:"password" binding:"MaxSize(255)"` | |||
Website string `json:"website" binding:"MaxSize(50)"` | |||
Location string `json:"location" binding:"MaxSize(50)"` | |||
Active *bool `json:"active"` | |||
Admin *bool `json:"admin"` | |||
AllowGitHook *bool `json:"allow_git_hook"` | |||
AllowImportLocal *bool `json:"allow_import_local"` | |||
MaxRepoCreation *int `json:"max_repo_creation"` | |||
Email string `json:"email" binding:"Required;Email;MaxSize(254)"` | |||
Password string `json:"password" binding:"MaxSize(255)"` | |||
Website string `json:"website" binding:"MaxSize(50)"` | |||
Location string `json:"location" binding:"MaxSize(50)"` | |||
Active *bool `json:"active"` | |||
Admin *bool `json:"admin"` | |||
AllowGitHook *bool `json:"allow_git_hook"` | |||
AllowImportLocal *bool `json:"allow_import_local"` | |||
MaxRepoCreation *int `json:"max_repo_creation"` | |||
} | |||
// AdminEditUser modify user informations |
@@ -3,15 +3,90 @@ | |||
// license that can be found in the LICENSE file. | |||
package gitea // import "code.gitea.io/sdk/gitea" | |||
import "time" | |||
import ( | |||
"bytes" | |||
"encoding/json" | |||
"fmt" | |||
"io" | |||
"mime/multipart" | |||
"net/http" | |||
"time" | |||
) | |||
// Attachment a generic attachment | |||
// swagger:model | |||
type Attachment struct { | |||
ID int64 `json:"id"` | |||
Name string `json:"name"` | |||
Size int64 `json:"size"` | |||
DownloadCount int64 `json:"download_count"` | |||
Created time.Time `json:"created_at"` | |||
UUID string `json:"uuid"` | |||
DownloadURL string `json:"browser_download_url"` | |||
ID int64 `json:"id"` | |||
Name string `json:"name"` | |||
Size int64 `json:"size"` | |||
DownloadCount int64 `json:"download_count"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
UUID string `json:"uuid"` | |||
DownloadURL string `json:"browser_download_url"` | |||
} | |||
// ListReleaseAttachments list release's attachments | |||
func (c *Client) ListReleaseAttachments(user, repo string, release int64) ([]*Attachment, error) { | |||
attachments := make([]*Attachment, 0, 10) | |||
err := c.getParsedResponse("GET", | |||
fmt.Sprintf("/repos/%s/%s/releases/%d/assets", user, repo, release), | |||
nil, nil, &attachments) | |||
return attachments, err | |||
} | |||
// ListReleaseAttachments list release's attachments | |||
func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, error) { | |||
a := new(Attachment) | |||
err := c.getParsedResponse("GET", | |||
fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), | |||
nil, nil, &a) | |||
return a, err | |||
} | |||
// CreateReleaseAttachment creates an attachment for the given release | |||
func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, error) { | |||
// Write file to body | |||
body := new(bytes.Buffer) | |||
writer := multipart.NewWriter(body) | |||
part, err := writer.CreateFormFile("attachment", filename) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if _, err = io.Copy(part, file); err != nil { | |||
return nil, err | |||
} | |||
if err = writer.Close(); err != nil { | |||
return nil, err | |||
} | |||
// Send request | |||
attachment := new(Attachment) | |||
err = c.getParsedResponse("POST", | |||
fmt.Sprintf("/repos/%s/%s/releases/%d/assets", user, repo, release), | |||
http.Header{"Content-Type": {writer.FormDataContentType()}}, body, &attachment) | |||
return attachment, err | |||
} | |||
// EditReleaseAttachment updates the given attachment with the given options | |||
func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachment int64, form EditAttachmentOptions) (*Attachment, error) { | |||
body, err := json.Marshal(&form) | |||
if err != nil { | |||
return nil, err | |||
} | |||
attach := new(Attachment) | |||
return attach, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, attachment), jsonHeader, bytes.NewReader(body), attach) | |||
} | |||
// DeleteReleaseAttachment deletes the given attachment including the uploaded file | |||
func (c *Client) DeleteReleaseAttachment(user, repo string, release int64, id int64) error { | |||
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil) | |||
return err | |||
} | |||
// EditAttachmentOptions options for editing attachments | |||
// swagger:model | |||
type EditAttachmentOptions struct { | |||
Name string `json:"name"` | |||
} |
@@ -7,6 +7,7 @@ package gitea | |||
import ( | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"io" | |||
"io/ioutil" | |||
"net/http" | |||
@@ -69,6 +70,8 @@ func (c *Client) getResponse(method, path string, header http.Header, body io.Re | |||
return nil, errors.New("403 Forbidden") | |||
case 404: | |||
return nil, errors.New("404 Not Found") | |||
case 422: | |||
return nil, fmt.Errorf("422 Unprocessable Entity: %s", string(data)) | |||
} | |||
if resp.StatusCode/100 != 2 { |
@@ -21,16 +21,16 @@ var ( | |||
// Hook a hook is a web hook when one repository changed | |||
type Hook struct { | |||
ID int64 `json:"id"` | |||
Type string `json:"type"` | |||
URL string `json:"-"` | |||
Config map[string]string `json:"config"` | |||
Events []string `json:"events"` | |||
Active bool `json:"active"` | |||
ID int64 `json:"id"` | |||
Type string `json:"type"` | |||
URL string `json:"-"` | |||
Config map[string]string `json:"config"` | |||
Events []string `json:"events"` | |||
Active bool `json:"active"` | |||
// swagger:strfmt date-time | |||
Updated time.Time `json:"updated_at"` | |||
Updated time.Time `json:"updated_at"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
Created time.Time `json:"created_at"` | |||
} | |||
// HookList represents a list of API hook. | |||
@@ -67,7 +67,7 @@ type CreateHookOption struct { | |||
Type string `json:"type" binding:"Required"` | |||
// required: true | |||
Config map[string]string `json:"config" binding:"Required"` | |||
Events []string `json:"events"` | |||
Events []string `json:"events"` | |||
// default: false | |||
Active bool `json:"active"` | |||
} | |||
@@ -95,8 +95,8 @@ func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, | |||
// EditHookOption options when modify one hook | |||
type EditHookOption struct { | |||
Config map[string]string `json:"config"` | |||
Events []string `json:"events"` | |||
Active *bool `json:"active"` | |||
Events []string `json:"events"` | |||
Active *bool `json:"active"` | |||
} | |||
// EditOrgHook modify one hook of an organization, with hook id and options | |||
@@ -140,7 +140,7 @@ type Payloader interface { | |||
// PayloadUser represents the author or committer of a commit | |||
type PayloadUser struct { | |||
// Full name of the commit author | |||
Name string `json:"name"` | |||
Name string `json:"name"` | |||
// swagger:strfmt email | |||
Email string `json:"email"` | |||
UserName string `json:"username"` | |||
@@ -159,7 +159,7 @@ type PayloadCommit struct { | |||
Committer *PayloadUser `json:"committer"` | |||
Verification *PayloadCommitVerification `json:"verification"` | |||
// swagger:strfmt date-time | |||
Timestamp time.Time `json:"timestamp"` | |||
Timestamp time.Time `json:"timestamp"` | |||
} | |||
// PayloadCommitVerification represents the GPG verification of a commit |
@@ -43,12 +43,12 @@ type Issue struct { | |||
// | |||
// type: string | |||
// enum: open,closed | |||
State StateType `json:"state"` | |||
Comments int `json:"comments"` | |||
State StateType `json:"state"` | |||
Comments int `json:"comments"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
Created time.Time `json:"created_at"` | |||
// swagger:strfmt date-time | |||
Updated time.Time `json:"updated_at"` | |||
Updated time.Time `json:"updated_at"` | |||
PullRequest *PullRequestMeta `json:"pull_request"` | |||
} | |||
@@ -86,15 +86,15 @@ func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, error) { | |||
// CreateIssueOption options to create one issue | |||
type CreateIssueOption struct { | |||
// required:true | |||
Title string `json:"title" binding:"Required"` | |||
Body string `json:"body"` | |||
Title string `json:"title" binding:"Required"` | |||
Body string `json:"body"` | |||
// username of assignee | |||
Assignee string `json:"assignee"` | |||
Assignee string `json:"assignee"` | |||
// milestone id | |||
Milestone int64 `json:"milestone"` | |||
Milestone int64 `json:"milestone"` | |||
// list of label ids | |||
Labels []int64 `json:"labels"` | |||
Closed bool `json:"closed"` | |||
Labels []int64 `json:"labels"` | |||
Closed bool `json:"closed"` | |||
} | |||
// CreateIssue create a new issue for a given repository |
@@ -13,16 +13,16 @@ import ( | |||
// Comment represents a comment on a commit or issue | |||
type Comment struct { | |||
ID int64 `json:"id"` | |||
HTMLURL string `json:"html_url"` | |||
PRURL string `json:"pull_request_url"` | |||
IssueURL string `json:"issue_url"` | |||
Poster *User `json:"user"` | |||
Body string `json:"body"` | |||
ID int64 `json:"id"` | |||
HTMLURL string `json:"html_url"` | |||
PRURL string `json:"pull_request_url"` | |||
IssueURL string `json:"issue_url"` | |||
Poster *User `json:"user"` | |||
Body string `json:"body"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
Created time.Time `json:"created_at"` | |||
// swagger:strfmt date-time | |||
Updated time.Time `json:"updated_at"` | |||
Updated time.Time `json:"updated_at"` | |||
} | |||
// ListIssueComments list comments on an issue. |
@@ -13,8 +13,8 @@ import ( | |||
// Label a label to an issue or a pr | |||
// swagger:model | |||
type Label struct { | |||
ID int64 `json:"id"` | |||
Name string `json:"name"` | |||
ID int64 `json:"id"` | |||
Name string `json:"name"` | |||
// example: 00aabb | |||
Color string `json:"color"` | |||
URL string `json:"url"` | |||
@@ -36,7 +36,7 @@ func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, error) { | |||
// CreateLabelOption options for creating a label | |||
type CreateLabelOption struct { | |||
// required:true | |||
Name string `json:"name" binding:"Required"` | |||
Name string `json:"name" binding:"Required"` | |||
// required:true | |||
// example: #00aabb | |||
Color string `json:"color" binding:"Required;Size(7)"` |
@@ -13,16 +13,16 @@ import ( | |||
// Milestone milestone is a collection of issues on one repository | |||
type Milestone struct { | |||
ID int64 `json:"id"` | |||
Title string `json:"title"` | |||
Description string `json:"description"` | |||
State StateType `json:"state"` | |||
OpenIssues int `json:"open_issues"` | |||
ClosedIssues int `json:"closed_issues"` | |||
ID int64 `json:"id"` | |||
Title string `json:"title"` | |||
Description string `json:"description"` | |||
State StateType `json:"state"` | |||
OpenIssues int `json:"open_issues"` | |||
ClosedIssues int `json:"closed_issues"` | |||
// swagger:strfmt date-time | |||
Closed *time.Time `json:"closed_at"` | |||
Closed *time.Time `json:"closed_at"` | |||
// swagger:strfmt date-time | |||
Deadline *time.Time `json:"due_on"` | |||
Deadline *time.Time `json:"due_on"` | |||
} | |||
// ListRepoMilestones list all the milestones of one repository | |||
@@ -39,10 +39,10 @@ func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, error) | |||
// CreateMilestoneOption options for creating a milestone | |||
type CreateMilestoneOption struct { | |||
Title string `json:"title"` | |||
Description string `json:"description"` | |||
Title string `json:"title"` | |||
Description string `json:"description"` | |||
// swagger:strfmt date-time | |||
Deadline *time.Time `json:"due_on"` | |||
Deadline *time.Time `json:"due_on"` | |||
} | |||
// CreateMilestone create one milestone with options |
@@ -13,7 +13,7 @@ import ( | |||
// TrackedTime worked time for an issue / pr | |||
type TrackedTime struct { | |||
ID int64 `json:"id"` | |||
ID int64 `json:"id"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created"` | |||
// Time in seconds |
@@ -42,11 +42,11 @@ func (c *Client) GetOrg(orgname string) (*Organization, error) { | |||
// CreateOrgOption options for creating an organization | |||
type CreateOrgOption struct { | |||
// required: true | |||
UserName string `json:"username" binding:"Required"` | |||
FullName string `json:"full_name"` | |||
UserName string `json:"username" binding:"Required"` | |||
FullName string `json:"full_name"` | |||
Description string `json:"description"` | |||
Website string `json:"website"` | |||
Location string `json:"location"` | |||
Website string `json:"website"` | |||
Location string `json:"location"` | |||
} | |||
// EditOrgOption options for editing an organization |
@@ -10,7 +10,7 @@ type Team struct { | |||
Name string `json:"name"` | |||
Description string `json:"description"` | |||
// enum: none,read,write,admin,owner | |||
Permission string `json:"permission"` | |||
Permission string `json:"permission"` | |||
} | |||
// CreateTeamOption options for creating a team | |||
@@ -19,7 +19,7 @@ type CreateTeamOption struct { | |||
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"` | |||
Description string `json:"description" binding:"MaxSize(255)"` | |||
// enum: read,write,admin | |||
Permission string `json:"permission"` | |||
Permission string `json:"permission"` | |||
} | |||
// EditTeamOption options for editing a team | |||
@@ -28,5 +28,5 @@ type EditTeamOption struct { | |||
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"` | |||
Description string `json:"description" binding:"MaxSize(255)"` | |||
// enum: read,write,admin | |||
Permission string `json:"permission"` | |||
Permission string `json:"permission"` | |||
} |
@@ -29,8 +29,8 @@ type PullRequest struct { | |||
DiffURL string `json:"diff_url"` | |||
PatchURL string `json:"patch_url"` | |||
Mergeable bool `json:"mergeable"` | |||
HasMerged bool `json:"merged"` | |||
Mergeable bool `json:"mergeable"` | |||
HasMerged bool `json:"merged"` | |||
// swagger:strfmt date-time | |||
Merged *time.Time `json:"merged_at"` | |||
MergedCommitID *string `json:"merge_commit_sha"` |
@@ -13,21 +13,22 @@ import ( | |||
// 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"` | |||
TarURL string `json:"tarball_url"` | |||
ZipURL string `json:"zipball_url"` | |||
IsDraft bool `json:"draft"` | |||
IsPrerelease bool `json:"prerelease"` | |||
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"` | |||
TarURL string `json:"tarball_url"` | |||
ZipURL string `json:"zipball_url"` | |||
IsDraft bool `json:"draft"` | |||
IsPrerelease bool `json:"prerelease"` | |||
// swagger:strfmt date-time | |||
CreatedAt time.Time `json:"created_at"` | |||
CreatedAt time.Time `json:"created_at"` | |||
// swagger:strfmt date-time | |||
PublishedAt time.Time `json:"published_at"` | |||
Publisher *User `json:"author"` | |||
PublishedAt time.Time `json:"published_at"` | |||
Publisher *User `json:"author"` | |||
Attachments []*Attachment `json:"assets"` | |||
} | |||
// ListReleases list releases of a repository |
@@ -41,10 +41,10 @@ type Repository struct { | |||
OpenIssues int `json:"open_issues_count"` | |||
DefaultBranch string `json:"default_branch"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
Created time.Time `json:"created_at"` | |||
// swagger:strfmt date-time | |||
Updated time.Time `json:"updated_at"` | |||
Permissions *Permission `json:"permissions,omitempty"` | |||
Updated time.Time `json:"updated_at"` | |||
Permissions *Permission `json:"permissions,omitempty"` | |||
} | |||
// ListMyRepos lists all repositories for the authenticated user that has access to. | |||
@@ -122,15 +122,15 @@ func (c *Client) DeleteRepo(owner, repo string) error { | |||
// MigrateRepoOption options for migrating a repository from an external service | |||
type MigrateRepoOption struct { | |||
// required: true | |||
CloneAddr string `json:"clone_addr" binding:"Required"` | |||
CloneAddr string `json:"clone_addr" binding:"Required"` | |||
AuthUsername string `json:"auth_username"` | |||
AuthPassword string `json:"auth_password"` | |||
// required: true | |||
UID int `json:"uid" binding:"Required"` | |||
// required: true | |||
RepoName string `json:"repo_name" binding:"Required"` | |||
Mirror bool `json:"mirror"` | |||
Private bool `json:"private"` | |||
RepoName string `json:"repo_name" binding:"Required"` | |||
Mirror bool `json:"mirror"` | |||
Private bool `json:"private"` | |||
Description string `json:"description"` | |||
} | |||
@@ -13,10 +13,10 @@ import ( | |||
// DeployKey a deploy key | |||
type DeployKey struct { | |||
ID int64 `json:"id"` | |||
Key string `json:"key"` | |||
URL string `json:"url"` | |||
Title string `json:"title"` | |||
ID int64 `json:"id"` | |||
Key string `json:"key"` | |||
URL string `json:"url"` | |||
Title string `json:"title"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
ReadOnly bool `json:"read_only"` |
@@ -38,9 +38,9 @@ type Status struct { | |||
Context string `json:"context"` | |||
Creator *User `json:"creator"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
Created time.Time `json:"created_at"` | |||
// swagger:strfmt date-time | |||
Updated time.Time `json:"updated_at"` | |||
Updated time.Time `json:"updated_at"` | |||
} | |||
// CombinedStatus holds the combined state of several statuses for a single commit |
@@ -13,13 +13,13 @@ import ( | |||
// swagger:model | |||
type User struct { | |||
// the user's id | |||
ID int64 `json:"id"` | |||
ID int64 `json:"id"` | |||
// the user's username | |||
UserName string `json:"login"` | |||
UserName string `json:"login"` | |||
// the user's full name | |||
FullName string `json:"full_name"` | |||
FullName string `json:"full_name"` | |||
// swagger:strfmt email | |||
Email string `json:"email"` | |||
Email string `json:"email"` | |||
// URL to the user's avatar | |||
AvatarURL string `json:"avatar_url"` | |||
} |
@@ -24,9 +24,9 @@ type GPGKey struct { | |||
CanEncryptStorage bool `json:"can_encrypt_storage"` | |||
CanCertify bool `json:"can_certify"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at,omitempty"` | |||
Created time.Time `json:"created_at,omitempty"` | |||
// swagger:strfmt date-time | |||
Expires time.Time `json:"expires_at,omitempty"` | |||
Expires time.Time `json:"expires_at,omitempty"` | |||
} | |||
// GPGKeyEmail an email attached to a GPGKey |
@@ -0,0 +1,14 @@ | |||
package gitea | |||
import "fmt" | |||
type searchUsersResponse struct { | |||
Users []*User `json:"data"` | |||
} | |||
// SearchUsers finds users by query | |||
func (c *Client) SearchUsers(query string, limit int) ([]*User, error) { | |||
resp := new(searchUsersResponse) | |||
err := c.getParsedResponse("GET", fmt.Sprintf("/users/search?q=%s&limit=%d", query, limit), nil, nil, &resp) | |||
return resp.Users, err | |||
} |
@@ -9,10 +9,10 @@ | |||
"revisionTime": "2018-02-10T03:05:43Z" | |||
}, | |||
{ | |||
"checksumSHA1": "Qtq0kW+BnpYMOriaoCjMa86WGG8=", | |||
"checksumSHA1": "PWaIU7g1YSkETxka2DIS1EYsPK0=", | |||
"path": "code.gitea.io/sdk/gitea", | |||
"revision": "79eee8f12c7fc1cc5b802c5cdc5b494ef3733866", | |||
"revisionTime": "2017-12-20T06:57:50Z" | |||
"revision": "cdbef997666132599cc92dc22aa94de3db04adeb", | |||
"revisionTime": "2018-03-02T14:48:43Z" | |||
}, | |||
{ | |||
"checksumSHA1": "bOODD4Gbw3GfcuQPU2dI40crxxk=", |