Skip to content

Commit efc2496

Browse files
committed
fix
1 parent e03a68c commit efc2496

File tree

5 files changed

+58
-50
lines changed

5 files changed

+58
-50
lines changed

modules/structs/repo_file.go

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,6 @@ type FileOptions struct {
2424
Signoff bool `json:"signoff"`
2525
}
2626

27-
type FileOptionsWithSHA struct {
28-
FileOptions
29-
// the blob ID (SHA) for the file that already exists, it is required for changing existing files
30-
// required: true
31-
SHA string `json:"sha" binding:"Required"`
32-
}
33-
3427
func (f *FileOptions) GetFileOptions() *FileOptions {
3528
return f
3629
}
@@ -41,7 +34,7 @@ type FileOptionsInterface interface {
4134

4235
var _ FileOptionsInterface = (*FileOptions)(nil)
4336

44-
// CreateFileOptions options for creating files
37+
// CreateFileOptions options for creating a file
4538
// 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)
4639
type CreateFileOptions struct {
4740
FileOptions
@@ -50,16 +43,21 @@ type CreateFileOptions struct {
5043
ContentBase64 string `json:"content"`
5144
}
5245

53-
// DeleteFileOptions options for deleting files (used for other File structs below)
46+
// DeleteFileOptions options for deleting a file
5447
// 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)
5548
type DeleteFileOptions struct {
56-
FileOptionsWithSHA
49+
FileOptions
50+
// the blob ID (SHA) for the file to delete
51+
// required: true
52+
SHA string `json:"sha" binding:"Required"`
5753
}
5854

59-
// UpdateFileOptions options for updating files
55+
// UpdateFileOptions options for updating or creating a file
6056
// 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)
6157
type UpdateFileOptions struct {
62-
FileOptionsWithSHA
58+
FileOptions
59+
// the blob ID (SHA) for the file that already exists to update, or leave it empty to create a new file
60+
SHA string `json:"sha"`
6361
// content must be base64 encoded
6462
// required: true
6563
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: 9 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integration/api_repo_file_delete_test.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,19 @@ import (
2020

2121
func getDeleteFileOptions() *api.DeleteFileOptions {
2222
return &api.DeleteFileOptions{
23-
FileOptionsWithSHA: api.FileOptionsWithSHA{
24-
FileOptions: api.FileOptions{
25-
BranchName: "master",
26-
NewBranchName: "master",
27-
Message: "Removing the file new/file.txt",
28-
Author: api.Identity{
29-
Name: "John Doe",
30-
31-
},
32-
Committer: api.Identity{
33-
Name: "Jane Doe",
34-
35-
},
23+
SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
24+
FileOptions: api.FileOptions{
25+
BranchName: "master",
26+
NewBranchName: "master",
27+
Message: "Removing the file new/file.txt",
28+
Author: api.Identity{
29+
Name: "John Doe",
30+
31+
},
32+
Committer: api.Identity{
33+
Name: "Jane Doe",
34+
3635
},
37-
SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885",
3836
},
3937
}
4038
}

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)