code.gitea.io/gitea@v1.22.3/routers/api/v1/repo/patch.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repo 5 6 import ( 7 "net/http" 8 "time" 9 10 "code.gitea.io/gitea/models" 11 git_model "code.gitea.io/gitea/models/git" 12 repo_model "code.gitea.io/gitea/models/repo" 13 "code.gitea.io/gitea/modules/git" 14 api "code.gitea.io/gitea/modules/structs" 15 "code.gitea.io/gitea/modules/web" 16 "code.gitea.io/gitea/services/context" 17 "code.gitea.io/gitea/services/repository/files" 18 ) 19 20 // ApplyDiffPatch handles API call for applying a patch 21 func ApplyDiffPatch(ctx *context.APIContext) { 22 // swagger:operation POST /repos/{owner}/{repo}/diffpatch repository repoApplyDiffPatch 23 // --- 24 // summary: Apply diff patch to repository 25 // consumes: 26 // - application/json 27 // produces: 28 // - application/json 29 // parameters: 30 // - name: owner 31 // in: path 32 // description: owner of the repo 33 // type: string 34 // required: true 35 // - name: repo 36 // in: path 37 // description: name of the repo 38 // type: string 39 // required: true 40 // - name: body 41 // in: body 42 // required: true 43 // schema: 44 // "$ref": "#/definitions/UpdateFileOptions" 45 // responses: 46 // "200": 47 // "$ref": "#/responses/FileResponse" 48 // "404": 49 // "$ref": "#/responses/notFound" 50 // "423": 51 // "$ref": "#/responses/repoArchivedError" 52 apiOpts := web.GetForm(ctx).(*api.ApplyDiffPatchFileOptions) 53 54 opts := &files.ApplyDiffPatchOptions{ 55 Content: apiOpts.Content, 56 SHA: apiOpts.SHA, 57 Message: apiOpts.Message, 58 OldBranch: apiOpts.BranchName, 59 NewBranch: apiOpts.NewBranchName, 60 Committer: &files.IdentityOptions{ 61 Name: apiOpts.Committer.Name, 62 Email: apiOpts.Committer.Email, 63 }, 64 Author: &files.IdentityOptions{ 65 Name: apiOpts.Author.Name, 66 Email: apiOpts.Author.Email, 67 }, 68 Dates: &files.CommitDateOptions{ 69 Author: apiOpts.Dates.Author, 70 Committer: apiOpts.Dates.Committer, 71 }, 72 Signoff: apiOpts.Signoff, 73 } 74 if opts.Dates.Author.IsZero() { 75 opts.Dates.Author = time.Now() 76 } 77 if opts.Dates.Committer.IsZero() { 78 opts.Dates.Committer = time.Now() 79 } 80 81 if opts.Message == "" { 82 opts.Message = "apply-patch" 83 } 84 85 if !canWriteFiles(ctx, apiOpts.BranchName) { 86 ctx.Error(http.StatusInternalServerError, "ApplyPatch", repo_model.ErrUserDoesNotHaveAccessToRepo{ 87 UserID: ctx.Doer.ID, 88 RepoName: ctx.Repo.Repository.LowerName, 89 }) 90 return 91 } 92 93 fileResponse, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, opts) 94 if err != nil { 95 if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) { 96 ctx.Error(http.StatusForbidden, "Access", err) 97 return 98 } 99 if git_model.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) || 100 models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) { 101 ctx.Error(http.StatusUnprocessableEntity, "Invalid", err) 102 return 103 } 104 if git_model.IsErrBranchNotExist(err) || git.IsErrBranchNotExist(err) { 105 ctx.Error(http.StatusNotFound, "BranchDoesNotExist", err) 106 return 107 } 108 ctx.Error(http.StatusInternalServerError, "ApplyPatch", err) 109 } else { 110 ctx.JSON(http.StatusCreated, fileResponse) 111 } 112 }