diff options
author | Denys Konovalov <privat@denyskon.de> | 2023-05-29 11:41:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-29 17:41:35 +0800 |
commit | 275d4b7e3f4595206e5c4b1657d4f6d6969d9ce2 (patch) | |
tree | 4283f97bce56c7783e6c77c380cbe4ce06277720 /tests | |
parent | 245f2c08db34e535576633748fc143bb09097ca8 (diff) | |
download | gitea-275d4b7e3f4595206e5c4b1657d4f6d6969d9ce2.tar.gz gitea-275d4b7e3f4595206e5c4b1657d4f6d6969d9ce2.zip |
API endpoint for changing/creating/deleting multiple files (#24887)
This PR creates an API endpoint for creating/updating/deleting multiple
files in one API call similar to the solution provided by
[GitLab](https://docs.gitlab.com/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions).
To archive this, the CreateOrUpdateRepoFile and DeleteRepoFIle functions
in files service are unified into one function supporting multiple files
and actions.
Resolves #14619
Diffstat (limited to 'tests')
-rw-r--r-- | tests/integration/api_repo_file_helpers.go | 18 | ||||
-rw-r--r-- | tests/integration/api_repo_files_change_test.go | 309 | ||||
-rw-r--r-- | tests/integration/pull_merge_test.go | 24 | ||||
-rw-r--r-- | tests/integration/pull_update_test.go | 24 | ||||
-rw-r--r-- | tests/integration/repofiles_change_test.go (renamed from tests/integration/repofiles_update_test.go) | 283 | ||||
-rw-r--r-- | tests/integration/repofiles_delete_test.go | 201 |
6 files changed, 559 insertions, 300 deletions
diff --git a/tests/integration/api_repo_file_helpers.go b/tests/integration/api_repo_file_helpers.go index d773bcd629..8e9b2bfecc 100644 --- a/tests/integration/api_repo_file_helpers.go +++ b/tests/integration/api_repo_file_helpers.go @@ -11,18 +11,22 @@ import ( files_service "code.gitea.io/gitea/services/repository/files" ) -func createFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName, content string) (*api.FileResponse, error) { - opts := &files_service.UpdateRepoFileOptions{ +func createFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName, content string) (*api.FilesResponse, error) { + opts := &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: treePath, + Content: content, + }, + }, OldBranch: branchName, - TreePath: treePath, - Content: content, - IsNewFile: true, Author: nil, Committer: nil, } - return files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, user, opts) + return files_service.ChangeRepoFiles(git.DefaultContext, repo, user, opts) } -func createFile(user *user_model.User, repo *repo_model.Repository, treePath string) (*api.FileResponse, error) { +func createFile(user *user_model.User, repo *repo_model.Repository, treePath string) (*api.FilesResponse, error) { return createFileInBranch(user, repo, treePath, repo.DefaultBranch, "This is a NEW file") } diff --git a/tests/integration/api_repo_files_change_test.go b/tests/integration/api_repo_files_change_test.go new file mode 100644 index 0000000000..38187ec5b9 --- /dev/null +++ b/tests/integration/api_repo_files_change_test.go @@ -0,0 +1,309 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + stdCtx "context" + "encoding/base64" + "fmt" + "net/http" + "net/url" + "testing" + + auth_model "code.gitea.io/gitea/models/auth" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" + + "github.com/stretchr/testify/assert" +) + +func getChangeFilesOptions() *api.ChangeFilesOptions { + newContent := "This is new text" + updateContent := "This is updated text" + newContentEncoded := base64.StdEncoding.EncodeToString([]byte(newContent)) + updateContentEncoded := base64.StdEncoding.EncodeToString([]byte(updateContent)) + return &api.ChangeFilesOptions{ + FileOptions: api.FileOptions{ + BranchName: "master", + NewBranchName: "master", + Message: "My update of new/file.txt", + Author: api.Identity{ + Name: "Anne Doe", + Email: "annedoe@example.com", + }, + Committer: api.Identity{ + Name: "John Doe", + Email: "johndoe@example.com", + }, + }, + Files: []*api.ChangeFileOperation{ + { + Operation: "create", + Content: newContentEncoded, + }, + { + Operation: "update", + Content: updateContentEncoded, + SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885", + }, + { + Operation: "delete", + SHA: "103ff9234cefeee5ec5361d22b49fbb04d385885", + }, + }, + } +} + +func TestAPIChangeFiles(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16 + user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the repo3, is an org + user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // owner of neither repos + repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo + repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo + repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo + fileID := 0 + + // Get user2's token + session := loginUser(t, user2.Name) + token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo) + // Get user4's token + session = loginUser(t, user4.Name) + token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo) + + // Test changing files in repo1 which user2 owns, try both with branch and empty branch + for _, branch := range [...]string{ + "master", // Branch + "", // Empty branch + } { + fileID++ + createTreePath := fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath := fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath := fmt.Sprintf("delete/file%d.txt", fileID) + createFile(user2, repo1, updateTreePath) + createFile(user2, repo1, deleteTreePath) + changeFilesOptions := getChangeFilesOptions() + changeFilesOptions.BranchName = branch + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + url := fmt.Sprintf("/api/v1/repos/%s/%s/contents?token=%s", user2.Name, repo1.Name, token2) + req := NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + resp := MakeRequest(t, req, http.StatusCreated) + gitRepo, _ := git.OpenRepository(stdCtx.Background(), repo1.RepoPath()) + commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName) + createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath) + updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath) + expectedCreateFileResponse := getExpectedFileResponseForCreate(fmt.Sprintf("%v/%v", user2.Name, repo1.Name), commitID, createTreePath, createLasCommit.ID.String()) + expectedUpdateFileResponse := getExpectedFileResponseForUpdate(commitID, updateTreePath, updateLastCommit.ID.String()) + var filesResponse api.FilesResponse + DecodeJSON(t, resp, &filesResponse) + + // check create file + assert.EqualValues(t, expectedCreateFileResponse.Content, filesResponse.Files[0]) + + // check update file + assert.EqualValues(t, expectedUpdateFileResponse.Content, filesResponse.Files[1]) + + // test commit info + assert.EqualValues(t, expectedCreateFileResponse.Commit.SHA, filesResponse.Commit.SHA) + assert.EqualValues(t, expectedCreateFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) + assert.EqualValues(t, expectedCreateFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) + assert.EqualValues(t, expectedCreateFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) + assert.EqualValues(t, expectedCreateFileResponse.Commit.Committer.Email, filesResponse.Commit.Committer.Email) + assert.EqualValues(t, expectedCreateFileResponse.Commit.Committer.Name, filesResponse.Commit.Committer.Name) + + // test delete file + assert.Nil(t, filesResponse.Files[2]) + + gitRepo.Close() + } + + // Test changing files in a new branch + changeFilesOptions := getChangeFilesOptions() + changeFilesOptions.BranchName = repo1.DefaultBranch + changeFilesOptions.NewBranchName = "new_branch" + fileID++ + createTreePath := fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath := fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath := fmt.Sprintf("delete/file%d.txt", fileID) + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + createFile(user2, repo1, updateTreePath) + createFile(user2, repo1, deleteTreePath) + url := fmt.Sprintf("/api/v1/repos/%s/%s/contents?token=%s", user2.Name, repo1.Name, token2) + req := NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + resp := MakeRequest(t, req, http.StatusCreated) + var filesResponse api.FilesResponse + DecodeJSON(t, resp, &filesResponse) + expectedCreateSHA := "a635aa942442ddfdba07468cf9661c08fbdf0ebf" + expectedCreateHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/new_branch/new/file%d.txt", fileID) + expectedCreateDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID) + expectedUpdateSHA := "08bd14b2e2852529157324de9c226b3364e76136" + expectedUpdateHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/new_branch/update/file%d.txt", fileID) + expectedUpdateDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID) + assert.EqualValues(t, expectedCreateSHA, filesResponse.Files[0].SHA) + assert.EqualValues(t, expectedCreateHTMLURL, *filesResponse.Files[0].HTMLURL) + assert.EqualValues(t, expectedCreateDownloadURL, *filesResponse.Files[0].DownloadURL) + assert.EqualValues(t, expectedUpdateSHA, filesResponse.Files[1].SHA) + assert.EqualValues(t, expectedUpdateHTMLURL, *filesResponse.Files[1].HTMLURL) + assert.EqualValues(t, expectedUpdateDownloadURL, *filesResponse.Files[1].DownloadURL) + assert.Nil(t, filesResponse.Files[2]) + + assert.EqualValues(t, changeFilesOptions.Message+"\n", filesResponse.Commit.Message) + + // Test updating a file and renaming it + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.BranchName = repo1.DefaultBranch + fileID++ + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + createFile(user2, repo1, updateTreePath) + changeFilesOptions.Files = []*api.ChangeFileOperation{changeFilesOptions.Files[1]} + changeFilesOptions.Files[0].FromPath = updateTreePath + changeFilesOptions.Files[0].Path = "rename/" + updateTreePath + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + resp = MakeRequest(t, req, http.StatusCreated) + DecodeJSON(t, resp, &filesResponse) + expectedUpdateSHA = "08bd14b2e2852529157324de9c226b3364e76136" + expectedUpdateHTMLURL = fmt.Sprintf(setting.AppURL+"user2/repo1/src/branch/master/rename/update/file%d.txt", fileID) + expectedUpdateDownloadURL = fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID) + assert.EqualValues(t, expectedUpdateSHA, filesResponse.Files[0].SHA) + assert.EqualValues(t, expectedUpdateHTMLURL, *filesResponse.Files[0].HTMLURL) + assert.EqualValues(t, expectedUpdateDownloadURL, *filesResponse.Files[0].DownloadURL) + + // Test updating a file without a message + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Message = "" + changeFilesOptions.BranchName = repo1.DefaultBranch + fileID++ + createTreePath = fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath = fmt.Sprintf("delete/file%d.txt", fileID) + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + createFile(user2, repo1, updateTreePath) + createFile(user2, repo1, deleteTreePath) + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + resp = MakeRequest(t, req, http.StatusCreated) + DecodeJSON(t, resp, &filesResponse) + expectedMessage := fmt.Sprintf("Add %v\nUpdate %v\nDelete %v\n", createTreePath, updateTreePath, deleteTreePath) + assert.EqualValues(t, expectedMessage, filesResponse.Commit.Message) + + // Test updating a file with the wrong SHA + fileID++ + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + createFile(user2, repo1, updateTreePath) + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Files = []*api.ChangeFileOperation{changeFilesOptions.Files[1]} + changeFilesOptions.Files[0].Path = updateTreePath + correctSHA := changeFilesOptions.Files[0].SHA + changeFilesOptions.Files[0].SHA = "badsha" + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + resp = MakeRequest(t, req, http.StatusUnprocessableEntity) + expectedAPIError := context.APIError{ + Message: "sha does not match [given: " + changeFilesOptions.Files[0].SHA + ", expected: " + correctSHA + "]", + URL: setting.API.SwaggerURL, + } + var apiError context.APIError + DecodeJSON(t, resp, &apiError) + assert.Equal(t, expectedAPIError, apiError) + + // Test creating a file in repo1 by user4 who does not have write access + fileID++ + createTreePath = fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath = fmt.Sprintf("delete/file%d.txt", fileID) + createFile(user2, repo16, updateTreePath) + createFile(user2, repo16, deleteTreePath) + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + url = fmt.Sprintf("/api/v1/repos/%s/%s/contents?token=%s", user2.Name, repo16.Name, token4) + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + MakeRequest(t, req, http.StatusNotFound) + + // Tests a repo with no token given so will fail + fileID++ + createTreePath = fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath = fmt.Sprintf("delete/file%d.txt", fileID) + createFile(user2, repo16, updateTreePath) + createFile(user2, repo16, deleteTreePath) + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + url = fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo16.Name) + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + MakeRequest(t, req, http.StatusNotFound) + + // Test using access token for a private repo that the user of the token owns + fileID++ + createTreePath = fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath = fmt.Sprintf("delete/file%d.txt", fileID) + createFile(user2, repo16, updateTreePath) + createFile(user2, repo16, deleteTreePath) + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + url = fmt.Sprintf("/api/v1/repos/%s/%s/contents?token=%s", user2.Name, repo16.Name, token2) + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + MakeRequest(t, req, http.StatusCreated) + + // Test using org repo "user3/repo3" where user2 is a collaborator + fileID++ + createTreePath = fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath = fmt.Sprintf("delete/file%d.txt", fileID) + createFile(user3, repo3, updateTreePath) + createFile(user3, repo3, deleteTreePath) + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + url = fmt.Sprintf("/api/v1/repos/%s/%s/contents?token=%s", user3.Name, repo3.Name, token2) + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + MakeRequest(t, req, http.StatusCreated) + + // Test using org repo "user3/repo3" with no user token + fileID++ + createTreePath = fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath = fmt.Sprintf("delete/file%d.txt", fileID) + createFile(user3, repo3, updateTreePath) + createFile(user3, repo3, deleteTreePath) + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + url = fmt.Sprintf("/api/v1/repos/%s/%s/contents", user3.Name, repo3.Name) + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + MakeRequest(t, req, http.StatusNotFound) + + // Test using repo "user2/repo1" where user4 is a NOT collaborator + fileID++ + createTreePath = fmt.Sprintf("new/file%d.txt", fileID) + updateTreePath = fmt.Sprintf("update/file%d.txt", fileID) + deleteTreePath = fmt.Sprintf("delete/file%d.txt", fileID) + createFile(user2, repo1, updateTreePath) + createFile(user2, repo1, deleteTreePath) + changeFilesOptions = getChangeFilesOptions() + changeFilesOptions.Files[0].Path = createTreePath + changeFilesOptions.Files[1].Path = updateTreePath + changeFilesOptions.Files[2].Path = deleteTreePath + url = fmt.Sprintf("/api/v1/repos/%s/%s/contents?token=%s", user2.Name, repo1.Name, token4) + req = NewRequestWithJSON(t, "POST", url, &changeFilesOptions) + MakeRequest(t, req, http.StatusForbidden) + }) +} diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index 9271f25e5f..f6a36f60af 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -367,22 +367,30 @@ func TestConflictChecking(t *testing.T) { assert.NotEmpty(t, baseRepo) // create a commit on new branch. - _, err = files_service.CreateOrUpdateRepoFile(git.DefaultContext, baseRepo, user, &files_service.UpdateRepoFileOptions{ - TreePath: "important_file", + _, err = files_service.ChangeRepoFiles(git.DefaultContext, baseRepo, user, &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "important_file", + Content: "Just a non-important file", + }, + }, Message: "Add a important file", - Content: "Just a non-important file", - IsNewFile: true, OldBranch: "main", NewBranch: "important-secrets", }) assert.NoError(t, err) // create a commit on main branch. - _, err = files_service.CreateOrUpdateRepoFile(git.DefaultContext, baseRepo, user, &files_service.UpdateRepoFileOptions{ - TreePath: "important_file", + _, err = files_service.ChangeRepoFiles(git.DefaultContext, baseRepo, user, &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "important_file", + Content: "Not the same content :P", + }, + }, Message: "Add a important file", - Content: "Not the same content :P", - IsNewFile: true, OldBranch: "main", NewBranch: "main", }) diff --git a/tests/integration/pull_update_test.go b/tests/integration/pull_update_test.go index 1b66656518..b94731002f 100644 --- a/tests/integration/pull_update_test.go +++ b/tests/integration/pull_update_test.go @@ -101,11 +101,15 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_mod assert.NotEmpty(t, headRepo) // create a commit on base Repo - _, err = files_service.CreateOrUpdateRepoFile(git.DefaultContext, baseRepo, actor, &files_service.UpdateRepoFileOptions{ - TreePath: "File_A", + _, err = files_service.ChangeRepoFiles(git.DefaultContext, baseRepo, actor, &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "File_A", + Content: "File A", + }, + }, Message: "Add File A", - Content: "File A", - IsNewFile: true, OldBranch: "master", NewBranch: "master", Author: &files_service.IdentityOptions{ @@ -124,11 +128,15 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_mod assert.NoError(t, err) // create a commit on head Repo - _, err = files_service.CreateOrUpdateRepoFile(git.DefaultContext, headRepo, actor, &files_service.UpdateRepoFileOptions{ - TreePath: "File_B", + _, err = files_service.ChangeRepoFiles(git.DefaultContext, headRepo, actor, &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "File_B", + Content: "File B", + }, + }, Message: "Add File on PR branch", - Content: "File B", - IsNewFile: true, OldBranch: "master", NewBranch: "newBranch", Author: &files_service.IdentityOptions{ diff --git a/tests/integration/repofiles_update_test.go b/tests/integration/repofiles_change_test.go index 47b61c1eeb..a257b95a84 100644 --- a/tests/integration/repofiles_update_test.go +++ b/tests/integration/repofiles_change_test.go @@ -10,6 +10,7 @@ import ( "time" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -19,33 +20,90 @@ import ( "github.com/stretchr/testify/assert" ) -func getCreateRepoFileOptions(repo *repo_model.Repository) *files_service.UpdateRepoFileOptions { - return &files_service.UpdateRepoFileOptions{ +func getCreateRepoFilesOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions { + return &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "new/file.txt", + Content: "This is a NEW file", + }, + }, OldBranch: repo.DefaultBranch, NewBranch: repo.DefaultBranch, - TreePath: "new/file.txt", Message: "Creates new/file.txt", - Content: "This is a NEW file", - IsNewFile: true, Author: nil, Committer: nil, } } -func getUpdateRepoFileOptions(repo *repo_model.Repository) *files_service.UpdateRepoFileOptions { - return &files_service.UpdateRepoFileOptions{ +func getUpdateRepoFilesOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions { + return &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "update", + TreePath: "README.md", + SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", + Content: "This is UPDATED content for the README file", + }, + }, OldBranch: repo.DefaultBranch, NewBranch: repo.DefaultBranch, - TreePath: "README.md", Message: "Updates README.md", - SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", - Content: "This is UPDATED content for the README file", - IsNewFile: false, Author: nil, Committer: nil, } } +func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.ChangeRepoFilesOptions { + return &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "delete", + TreePath: "README.md", + SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", + }, + }, + LastCommitID: "", + OldBranch: repo.DefaultBranch, + NewBranch: repo.DefaultBranch, + Message: "Deletes README.md", + Author: &files_service.IdentityOptions{ + Name: "Bob Smith", + Email: "bob@smith.com", + }, + Committer: nil, + } +} + +func getExpectedFileResponseForRepofilesDelete(u *url.URL) *api.FileResponse { + // Just returns fields that don't change, i.e. fields with commit SHAs and dates can't be determined + return &api.FileResponse{ + Content: nil, + Commit: &api.FileCommitResponse{ + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "Bob Smith", + Email: "bob@smith.com", + }, + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "Bob Smith", + Email: "bob@smith.com", + }, + }, + Message: "Deletes README.md\n", + }, + Verification: &api.PayloadCommitVerification{ + Verified: false, + Reason: "gpg.error.not_signed_commit", + Signature: "", + Payload: "", + }, + } +} + func getExpectedFileResponseForRepofilesCreate(commitID, lastCommitSHA string) *api.FileResponse { treePath := "new/file.txt" encoding := "base64" @@ -183,7 +241,7 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA } } -func TestCreateOrUpdateRepoFileForCreate(t *testing.T) { +func TestChangeRepoFilesForCreate(t *testing.T) { // setup onGiteaRun(t, func(t *testing.T, u *url.URL) { ctx := test.MockContext(t, "user2/repo1") @@ -196,10 +254,10 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) { repo := ctx.Repo.Repository doer := ctx.Doer - opts := getCreateRepoFileOptions(repo) + opts := getCreateRepoFilesOptions(repo) // test - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) // asserts assert.NoError(t, err) @@ -211,16 +269,16 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) { expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String()) assert.NotNil(t, expectedFileResponse) if expectedFileResponse != nil { - assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) - assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA) - assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name) + assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) + assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) + assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) } }) } -func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) { +func TestChangeRepoFilesForUpdate(t *testing.T) { // setup onGiteaRun(t, func(t *testing.T, u *url.URL) { ctx := test.MockContext(t, "user2/repo1") @@ -233,10 +291,10 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) { repo := ctx.Repo.Repository doer := ctx.Doer - opts := getUpdateRepoFileOptions(repo) + opts := getUpdateRepoFilesOptions(repo) // test - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) // asserts assert.NoError(t, err) @@ -244,17 +302,17 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) - lastCommit, _ := commit.GetCommitByPath(opts.TreePath) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath, lastCommit.ID.String()) - assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) - assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA) - assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name) + lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) + assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) + assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) + assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) }) } -func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) { +func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) { // setup onGiteaRun(t, func(t *testing.T, u *url.URL) { ctx := test.MockContext(t, "user2/repo1") @@ -267,12 +325,12 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) { repo := ctx.Repo.Repository doer := ctx.Doer - opts := getUpdateRepoFileOptions(repo) - opts.FromTreePath = "README.md" - opts.TreePath = "README_new.md" // new file name, README_new.md + opts := getUpdateRepoFilesOptions(repo) + opts.Files[0].FromTreePath = "README.md" + opts.Files[0].TreePath = "README_new.md" // new file name, README_new.md // test - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) // asserts assert.NoError(t, err) @@ -280,32 +338,32 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) - lastCommit, _ := commit.GetCommitByPath(opts.TreePath) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath, lastCommit.ID.String()) + lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) // assert that the old file no longer exists in the last commit of the branch - fromEntry, err := commit.GetTreeEntryByPath(opts.FromTreePath) + fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath) switch err.(type) { case git.ErrNotExist: // correct, continue default: t.Fatalf("expected git.ErrNotExist, got:%v", err) } - toEntry, err := commit.GetTreeEntryByPath(opts.TreePath) + toEntry, err := commit.GetTreeEntryByPath(opts.Files[0].TreePath) assert.NoError(t, err) assert.Nil(t, fromEntry) // Should no longer exist here assert.NotNil(t, toEntry) // Should exist here // assert SHA has remained the same but paths use the new file name - assert.EqualValues(t, expectedFileResponse.Content.SHA, fileResponse.Content.SHA) - assert.EqualValues(t, expectedFileResponse.Content.Name, fileResponse.Content.Name) - assert.EqualValues(t, expectedFileResponse.Content.Path, fileResponse.Content.Path) - assert.EqualValues(t, expectedFileResponse.Content.URL, fileResponse.Content.URL) - assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA) - assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL) + assert.EqualValues(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA) + assert.EqualValues(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name) + assert.EqualValues(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path) + assert.EqualValues(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL) + assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) + assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) }) } // Test opts with branch names removed, should get same results as above test -func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) { +func TestChangeRepoFilesWithoutBranchNames(t *testing.T) { // setup onGiteaRun(t, func(t *testing.T, u *url.URL) { ctx := test.MockContext(t, "user2/repo1") @@ -318,12 +376,12 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) { repo := ctx.Repo.Repository doer := ctx.Doer - opts := getUpdateRepoFileOptions(repo) + opts := getUpdateRepoFilesOptions(repo) opts.OldBranch = "" opts.NewBranch = "" // test - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) // asserts assert.NoError(t, err) @@ -331,13 +389,86 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) { defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) - lastCommit, _ := commit.GetCommitByPath(opts.TreePath) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath, lastCommit.ID.String()) - assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content) + lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) + assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) + }) +} + +func TestChangeRepoFilesForDelete(t *testing.T) { + onGiteaRun(t, testDeleteRepoFiles) +} + +func testDeleteRepoFiles(t *testing.T, u *url.URL) { + // setup + unittest.PrepareTestEnv(t) + ctx := test.MockContext(t, "user2/repo1") + ctx.SetParams(":id", "1") + test.LoadRepo(t, ctx, 1) + test.LoadRepoCommit(t, ctx) + test.LoadUser(t, ctx, 2) + test.LoadGitRepo(t, ctx) + defer ctx.Repo.GitRepo.Close() + repo := ctx.Repo.Repository + doer := ctx.Doer + opts := getDeleteRepoFilesOptions(repo) + + t.Run("Delete README.md file", func(t *testing.T) { + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.NoError(t, err) + expectedFileResponse := getExpectedFileResponseForRepofilesDelete(u) + assert.NotNil(t, filesResponse) + assert.Nil(t, filesResponse.Files[0]) + assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) + assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) + assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) + }) + + t.Run("Verify README.md has been deleted", func(t *testing.T) { + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.Nil(t, filesResponse) + expectedError := "repository file does not exist [path: " + opts.Files[0].TreePath + "]" + assert.EqualError(t, err, expectedError) }) } -func TestCreateOrUpdateRepoFileErrors(t *testing.T) { +// Test opts with branch names removed, same results +func TestChangeRepoFilesForDeleteWithoutBranchNames(t *testing.T) { + onGiteaRun(t, testDeleteRepoFilesWithoutBranchNames) +} + +func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) { + // setup + unittest.PrepareTestEnv(t) + ctx := test.MockContext(t, "user2/repo1") + ctx.SetParams(":id", "1") + test.LoadRepo(t, ctx, 1) + test.LoadRepoCommit(t, ctx) + test.LoadUser(t, ctx, 2) + test.LoadGitRepo(t, ctx) + defer ctx.Repo.GitRepo.Close() + + repo := ctx.Repo.Repository + doer := ctx.Doer + opts := getDeleteRepoFilesOptions(repo) + opts.OldBranch = "" + opts.NewBranch = "" + + t.Run("Delete README.md without Branch Name", func(t *testing.T) { + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.NoError(t, err) + expectedFileResponse := getExpectedFileResponseForRepofilesDelete(u) + assert.NotNil(t, filesResponse) + assert.Nil(t, filesResponse.Files[0]) + assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) + assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) + assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) + }) +} + +func TestChangeRepoFilesErrors(t *testing.T) { // setup onGiteaRun(t, func(t *testing.T, u *url.URL) { ctx := test.MockContext(t, "user2/repo1") @@ -352,63 +483,63 @@ func TestCreateOrUpdateRepoFileErrors(t *testing.T) { doer := ctx.Doer t.Run("bad branch", func(t *testing.T) { - opts := getUpdateRepoFileOptions(repo) + opts := getUpdateRepoFilesOptions(repo) opts.OldBranch = "bad_branch" - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) assert.Error(t, err) - assert.Nil(t, fileResponse) + assert.Nil(t, filesResponse) expectedError := "branch does not exist [name: " + opts.OldBranch + "]" assert.EqualError(t, err, expectedError) }) t.Run("bad SHA", func(t *testing.T) { - opts := getUpdateRepoFileOptions(repo) - origSHA := opts.SHA - opts.SHA = "bad_sha" - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) + opts := getUpdateRepoFilesOptions(repo) + origSHA := opts.Files[0].SHA + opts.Files[0].SHA = "bad_sha" + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.Nil(t, filesResponse) assert.Error(t, err) - expectedError := "sha does not match [given: " + opts.SHA + ", expected: " + origSHA + "]" + expectedError := "sha does not match [given: " + opts.Files[0].SHA + ", expected: " + origSHA + "]" assert.EqualError(t, err, expectedError) }) t.Run("new branch already exists", func(t *testing.T) { - opts := getUpdateRepoFileOptions(repo) + opts := getUpdateRepoFilesOptions(repo) opts.NewBranch = "develop" - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.Nil(t, filesResponse) assert.Error(t, err) expectedError := "branch already exists [name: " + opts.NewBranch + "]" assert.EqualError(t, err, expectedError) }) t.Run("treePath is empty:", func(t *testing.T) { - opts := getUpdateRepoFileOptions(repo) - opts.TreePath = "" - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) + opts := getUpdateRepoFilesOptions(repo) + opts.Files[0].TreePath = "" + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.Nil(t, filesResponse) assert.Error(t, err) expectedError := "path contains a malformed path component [path: ]" assert.EqualError(t, err, expectedError) }) t.Run("treePath is a git directory:", func(t *testing.T) { - opts := getUpdateRepoFileOptions(repo) - opts.TreePath = ".git" - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) + opts := getUpdateRepoFilesOptions(repo) + opts.Files[0].TreePath = ".git" + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.Nil(t, filesResponse) assert.Error(t, err) - expectedError := "path contains a malformed path component [path: " + opts.TreePath + "]" + expectedError := "path contains a malformed path component [path: " + opts.Files[0].TreePath + "]" assert.EqualError(t, err, expectedError) }) t.Run("create file that already exists", func(t *testing.T) { - opts := getCreateRepoFileOptions(repo) - opts.TreePath = "README.md" // already exists - fileResponse, err := files_service.CreateOrUpdateRepoFile(git.DefaultContext, repo, doer, opts) + opts := getCreateRepoFilesOptions(repo) + opts.Files[0].TreePath = "README.md" // already exists + fileResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) assert.Nil(t, fileResponse) assert.Error(t, err) - expectedError := "repository file already exists [path: " + opts.TreePath + "]" + expectedError := "repository file already exists [path: " + opts.Files[0].TreePath + "]" assert.EqualError(t, err, expectedError) }) }) diff --git a/tests/integration/repofiles_delete_test.go b/tests/integration/repofiles_delete_test.go deleted file mode 100644 index 6698b280bd..0000000000 --- a/tests/integration/repofiles_delete_test.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2019 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package integration - -import ( - "net/url" - "testing" - - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/git" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - files_service "code.gitea.io/gitea/services/repository/files" - - "github.com/stretchr/testify/assert" -) - -func getDeleteRepoFileOptions(repo *repo_model.Repository) *files_service.DeleteRepoFileOptions { - return &files_service.DeleteRepoFileOptions{ - LastCommitID: "", - OldBranch: repo.DefaultBranch, - NewBranch: repo.DefaultBranch, - TreePath: "README.md", - Message: "Deletes README.md", - SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", - Author: &files_service.IdentityOptions{ - Name: "Bob Smith", - Email: "bob@smith.com", - }, - Committer: nil, - } -} - -func getExpectedDeleteFileResponse(u *url.URL) *api.FileResponse { - // Just returns fields that don't change, i.e. fields with commit SHAs and dates can't be determined - return &api.FileResponse{ - Content: nil, - Commit: &api.FileCommitResponse{ - Author: &api.CommitUser{ - Identity: api.Identity{ - Name: "Bob Smith", - Email: "bob@smith.com", - }, - }, - Committer: &api.CommitUser{ - Identity: api.Identity{ - Name: "Bob Smith", - Email: "bob@smith.com", - }, - }, - Message: "Deletes README.md\n", - }, - Verification: &api.PayloadCommitVerification{ - Verified: false, - Reason: "gpg.error.not_signed_commit", - Signature: "", - Payload: "", - }, - } -} - -func TestDeleteRepoFile(t *testing.T) { - onGiteaRun(t, testDeleteRepoFile) -} - -func testDeleteRepoFile(t *testing.T, u *url.URL) { - // setup - unittest.PrepareTestEnv(t) - ctx := test.MockContext(t, "user2/repo1") - ctx.SetParams(":id", "1") - test.LoadRepo(t, ctx, 1) - test.LoadRepoCommit(t, ctx) - test.LoadUser(t, ctx, 2) - test.LoadGitRepo(t, ctx) - defer ctx.Repo.GitRepo.Close() - repo := ctx.Repo.Repository - doer := ctx.Doer - opts := getDeleteRepoFileOptions(repo) - - t.Run("Delete README.md file", func(t *testing.T) { - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.NoError(t, err) - expectedFileResponse := getExpectedDeleteFileResponse(u) - assert.NotNil(t, fileResponse) - assert.Nil(t, fileResponse.Content) - assert.EqualValues(t, expectedFileResponse.Commit.Message, fileResponse.Commit.Message) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, fileResponse.Commit.Author.Identity) - assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, fileResponse.Commit.Committer.Identity) - assert.EqualValues(t, expectedFileResponse.Verification, fileResponse.Verification) - }) - - t.Run("Verify README.md has been deleted", func(t *testing.T) { - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) - expectedError := "repository file does not exist [path: " + opts.TreePath + "]" - assert.EqualError(t, err, expectedError) - }) -} - -// Test opts with branch names removed, same results -func TestDeleteRepoFileWithoutBranchNames(t *testing.T) { - onGiteaRun(t, testDeleteRepoFileWithoutBranchNames) -} - -func testDeleteRepoFileWithoutBranchNames(t *testing.T, u *url.URL) { - // setup - unittest.PrepareTestEnv(t) - ctx := test.MockContext(t, "user2/repo1") - ctx.SetParams(":id", "1") - test.LoadRepo(t, ctx, 1) - test.LoadRepoCommit(t, ctx) - test.LoadUser(t, ctx, 2) - test.LoadGitRepo(t, ctx) - defer ctx.Repo.GitRepo.Close() - - repo := ctx.Repo.Repository - doer := ctx.Doer - opts := getDeleteRepoFileOptions(repo) - opts.OldBranch = "" - opts.NewBranch = "" - - t.Run("Delete README.md without Branch Name", func(t *testing.T) { - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.NoError(t, err) - expectedFileResponse := getExpectedDeleteFileResponse(u) - assert.NotNil(t, fileResponse) - assert.Nil(t, fileResponse.Content) - assert.EqualValues(t, expectedFileResponse.Commit.Message, fileResponse.Commit.Message) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, fileResponse.Commit.Author.Identity) - assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, fileResponse.Commit.Committer.Identity) - assert.EqualValues(t, expectedFileResponse.Verification, fileResponse.Verification) - }) -} - -func TestDeleteRepoFileErrors(t *testing.T) { - // setup - unittest.PrepareTestEnv(t) - ctx := test.MockContext(t, "user2/repo1") - ctx.SetParams(":id", "1") - test.LoadRepo(t, ctx, 1) - test.LoadRepoCommit(t, ctx) - test.LoadUser(t, ctx, 2) - test.LoadGitRepo(t, ctx) - defer ctx.Repo.GitRepo.Close() - - repo := ctx.Repo.Repository - doer := ctx.Doer - - t.Run("Bad branch", func(t *testing.T) { - opts := getDeleteRepoFileOptions(repo) - opts.OldBranch = "bad_branch" - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.Error(t, err) - assert.Nil(t, fileResponse) - expectedError := "branch does not exist [name: " + opts.OldBranch + "]" - assert.EqualError(t, err, expectedError) - }) - - t.Run("Bad SHA", func(t *testing.T) { - opts := getDeleteRepoFileOptions(repo) - origSHA := opts.SHA - opts.SHA = "bad_sha" - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) - assert.Error(t, err) - expectedError := "sha does not match [given: " + opts.SHA + ", expected: " + origSHA + "]" - assert.EqualError(t, err, expectedError) - }) - - t.Run("New branch already exists", func(t *testing.T) { - opts := getDeleteRepoFileOptions(repo) - opts.NewBranch = "develop" - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) - assert.Error(t, err) - expectedError := "branch already exists [name: " + opts.NewBranch + "]" - assert.EqualError(t, err, expectedError) - }) - - t.Run("TreePath is empty:", func(t *testing.T) { - opts := getDeleteRepoFileOptions(repo) - opts.TreePath = "" - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) - assert.Error(t, err) - expectedError := "path contains a malformed path component [path: ]" - assert.EqualError(t, err, expectedError) - }) - - t.Run("TreePath is a git directory:", func(t *testing.T) { - opts := getDeleteRepoFileOptions(repo) - opts.TreePath = ".git" - fileResponse, err := files_service.DeleteRepoFile(git.DefaultContext, repo, doer, opts) - assert.Nil(t, fileResponse) - assert.Error(t, err) - expectedError := "path contains a malformed path component [path: " + opts.TreePath + "]" - assert.EqualError(t, err, expectedError) - }) -} |