Skip to content

Commit 70739c3

Browse files
authored
Handle expected errors in FileCreate & FileUpdate API (#11643) (#11718)
as title needed for #11641
1 parent 249e22b commit 70739c3

File tree

4 files changed

+57
-4
lines changed

4 files changed

+57
-4
lines changed

integrations/api_repo_file_create_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func TestAPICreateFile(t *testing.T) {
189189
treePath = "README.md"
190190
url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
191191
req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
192-
resp = session.MakeRequest(t, req, http.StatusInternalServerError)
192+
resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity)
193193
expectedAPIError := context.APIError{
194194
Message: "repository file already exists [path: " + treePath + "]",
195195
URL: setting.API.SwaggerURL,

integrations/api_repo_file_update_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func TestAPIUpdateFile(t *testing.T) {
208208
updateFileOptions.SHA = "badsha"
209209
url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
210210
req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
211-
resp = session.MakeRequest(t, req, http.StatusInternalServerError)
211+
resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity)
212212
expectedAPIError := context.APIError{
213213
Message: "sha does not match [given: " + updateFileOptions.SHA + ", expected: " + correctSHA + "]",
214214
URL: setting.API.SwaggerURL,

routers/api/v1/repo/file.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package repo
77

88
import (
99
"encoding/base64"
10+
"fmt"
1011
"net/http"
1112
"time"
1213

@@ -198,6 +199,16 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) {
198199
// responses:
199200
// "201":
200201
// "$ref": "#/responses/FileResponse"
202+
// "403":
203+
// "$ref": "#/responses/error"
204+
// "404":
205+
// "$ref": "#/responses/notFound"
206+
// "422":
207+
// "$ref": "#/responses/error"
208+
209+
if ctx.Repo.Repository.IsEmpty {
210+
ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty"))
211+
}
201212

202213
if apiOpts.BranchName == "" {
203214
apiOpts.BranchName = ctx.Repo.Repository.DefaultBranch
@@ -235,7 +246,7 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) {
235246
}
236247

237248
if fileResponse, err := createOrUpdateFile(ctx, opts); err != nil {
238-
ctx.Error(http.StatusInternalServerError, "CreateFile", err)
249+
handleCreateOrUpdateFileError(ctx, err)
239250
} else {
240251
ctx.JSON(http.StatusCreated, fileResponse)
241252
}
@@ -274,6 +285,16 @@ func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) {
274285
// responses:
275286
// "200":
276287
// "$ref": "#/responses/FileResponse"
288+
// "403":
289+
// "$ref": "#/responses/error"
290+
// "404":
291+
// "$ref": "#/responses/notFound"
292+
// "422":
293+
// "$ref": "#/responses/error"
294+
295+
if ctx.Repo.Repository.IsEmpty {
296+
ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty"))
297+
}
277298

278299
if apiOpts.BranchName == "" {
279300
apiOpts.BranchName = ctx.Repo.Repository.DefaultBranch
@@ -313,12 +334,26 @@ func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) {
313334
}
314335

315336
if fileResponse, err := createOrUpdateFile(ctx, opts); err != nil {
316-
ctx.Error(http.StatusInternalServerError, "UpdateFile", err)
337+
handleCreateOrUpdateFileError(ctx, err)
317338
} else {
318339
ctx.JSON(http.StatusOK, fileResponse)
319340
}
320341
}
321342

343+
func handleCreateOrUpdateFileError(ctx *context.APIContext, err error) {
344+
if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) {
345+
ctx.Error(http.StatusForbidden, "Access", err)
346+
return
347+
}
348+
if models.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) ||
349+
models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) {
350+
ctx.Error(http.StatusUnprocessableEntity, "Invalid", err)
351+
return
352+
}
353+
354+
ctx.Error(http.StatusInternalServerError, "UpdateFile", err)
355+
}
356+
322357
// Called from both CreateFile or UpdateFile to handle both
323358
func createOrUpdateFile(ctx *context.APIContext, opts *repofiles.UpdateRepoFileOptions) (*api.FileResponse, error) {
324359
if !canWriteFiles(ctx.Repo) {

templates/swagger/v1_json.tmpl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2746,6 +2746,15 @@
27462746
"responses": {
27472747
"200": {
27482748
"$ref": "#/responses/FileResponse"
2749+
},
2750+
"403": {
2751+
"$ref": "#/responses/error"
2752+
},
2753+
"404": {
2754+
"$ref": "#/responses/notFound"
2755+
},
2756+
"422": {
2757+
"$ref": "#/responses/error"
27492758
}
27502759
}
27512760
},
@@ -2795,6 +2804,15 @@
27952804
"responses": {
27962805
"201": {
27972806
"$ref": "#/responses/FileResponse"
2807+
},
2808+
"403": {
2809+
"$ref": "#/responses/error"
2810+
},
2811+
"404": {
2812+
"$ref": "#/responses/notFound"
2813+
},
2814+
"422": {
2815+
"$ref": "#/responses/error"
27982816
}
27992817
}
28002818
},

0 commit comments

Comments
 (0)