summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDenys Konovalov <privat@denyskon.de>2023-05-29 11:41:35 +0200
committerGitHub <noreply@github.com>2023-05-29 17:41:35 +0800
commit275d4b7e3f4595206e5c4b1657d4f6d6969d9ce2 (patch)
tree4283f97bce56c7783e6c77c380cbe4ce06277720 /tests
parent245f2c08db34e535576633748fc143bb09097ca8 (diff)
downloadgitea-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.go18
-rw-r--r--tests/integration/api_repo_files_change_test.go309
-rw-r--r--tests/integration/pull_merge_test.go24
-rw-r--r--tests/integration/pull_update_test.go24
-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.go201
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)
- })
-}