Skip to content

Commit 20b92f7

Browse files
committed
fix
1 parent e03a68c commit 20b92f7

File tree

4 files changed

+41
-27
lines changed

4 files changed

+41
-27
lines changed

modules/structs/repo_file.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type FileOptionsInterface interface {
4141

4242
var _ FileOptionsInterface = (*FileOptions)(nil)
4343

44-
// CreateFileOptions options for creating files
44+
// CreateFileOptions options for creating a file
4545
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
4646
type CreateFileOptions struct {
4747
FileOptions
@@ -50,16 +50,18 @@ type CreateFileOptions struct {
5050
ContentBase64 string `json:"content"`
5151
}
5252

53-
// DeleteFileOptions options for deleting files (used for other File structs below)
53+
// DeleteFileOptions options for deleting a file
5454
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
5555
type DeleteFileOptions struct {
5656
FileOptionsWithSHA
5757
}
5858

59-
// UpdateFileOptions options for updating files
59+
// UpdateFileOptions options for updating or creating a file
6060
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
6161
type UpdateFileOptions struct {
62-
FileOptionsWithSHA
62+
FileOptions
63+
// the blob ID (SHA) for the file that already exists to update, or leave it empty to create a new file
64+
SHA string `json:"sha"`
6365
// content must be base64 encoded
6466
// required: true
6567
ContentBase64 string `json:"content"`

routers/api/v1/repo/file.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ func CreateFile(ctx *context.APIContext) {
525525
func UpdateFile(ctx *context.APIContext) {
526526
// swagger:operation PUT /repos/{owner}/{repo}/contents/{filepath} repository repoUpdateFile
527527
// ---
528-
// summary: Update a file in a repository
528+
// summary: Update a file in a repository if SHA is set, or create the file if SHA is not set
529529
// consumes:
530530
// - application/json
531531
// produces:
@@ -554,6 +554,8 @@ func UpdateFile(ctx *context.APIContext) {
554554
// responses:
555555
// "200":
556556
// "$ref": "#/responses/FileResponse"
557+
// "201":
558+
// "$ref": "#/responses/FileResponse"
557559
// "403":
558560
// "$ref": "#/responses/error"
559561
// "404":
@@ -572,8 +574,9 @@ func UpdateFile(ctx *context.APIContext) {
572574
ctx.APIError(http.StatusUnprocessableEntity, err)
573575
return
574576
}
577+
willCreate := apiOpts.SHA == ""
575578
opts.Files = append(opts.Files, &files_service.ChangeRepoFile{
576-
Operation: "update",
579+
Operation: util.Iif(willCreate, "create", "update"),
577580
ContentReader: contentReader,
578581
SHA: apiOpts.SHA,
579582
FromTreePath: apiOpts.FromPath,
@@ -587,7 +590,7 @@ func UpdateFile(ctx *context.APIContext) {
587590
handleChangeRepoFilesError(ctx, err)
588591
} else {
589592
fileResponse := files_service.GetFileResponseFromFilesResponse(filesResponse, 0)
590-
ctx.JSON(http.StatusOK, fileResponse)
593+
ctx.JSON(util.Iif(willCreate, http.StatusCreated, http.StatusOK), fileResponse)
591594
}
592595
}
593596

templates/swagger/v1_json.tmpl

Lines changed: 8 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/api_repo_file_update_test.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,19 @@ func getUpdateFileOptions() *api.UpdateFileOptions {
2828
content := "This is updated text"
2929
contentEncoded := base64.StdEncoding.EncodeToString([]byte(content))
3030
return &api.UpdateFileOptions{
31-
FileOptionsWithSHA: api.FileOptionsWithSHA{
32-
FileOptions: api.FileOptions{
33-
BranchName: "master",
34-
NewBranchName: "master",
35-
Message: "My update of new/file.txt",
36-
Author: api.Identity{
37-
Name: "John Doe",
38-
39-
},
40-
Committer: api.Identity{
41-
Name: "Anne Doe",
42-
43-
},
31+
SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
32+
FileOptions: api.FileOptions{
33+
BranchName: "master",
34+
NewBranchName: "master",
35+
Message: "My update of new/file.txt",
36+
Author: api.Identity{
37+
Name: "John Doe",
38+
39+
},
40+
Committer: api.Identity{
41+
Name: "Anne Doe",
42+
4443
},
45-
SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
4644
},
4745
ContentBase64: contentEncoded,
4846
}
@@ -180,6 +178,15 @@ func TestAPIUpdateFile(t *testing.T) {
180178
assert.Equal(t, expectedDownloadURL, *fileResponse.Content.DownloadURL)
181179
assert.Equal(t, updateFileOptions.Message+"\n", fileResponse.Commit.Message)
182180

181+
// Test updating a file without SHA (should create the file)
182+
updateFileOptions = getUpdateFileOptions()
183+
updateFileOptions.SHA = ""
184+
req = NewRequestWithJSON(t, "PUT", "/api/v1/repos/user2/repo1/contents/update-create.txt", &updateFileOptions).AddTokenAuth(token2)
185+
resp = MakeRequest(t, req, http.StatusCreated)
186+
DecodeJSON(t, resp, &fileResponse)
187+
assert.Equal(t, "08bd14b2e2852529157324de9c226b3364e76136", fileResponse.Content.SHA)
188+
assert.Equal(t, setting.AppURL+"user2/repo1/raw/branch/master/update-create.txt", *fileResponse.Content.DownloadURL)
189+
183190
// Test updating a file and renaming it
184191
updateFileOptions = getUpdateFileOptions()
185192
updateFileOptions.BranchName = repo1.DefaultBranch

0 commit comments

Comments
 (0)