* 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.21.12.1
| @@ -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=", | |||