]> source.dussan.org Git - gitea.git/commitdiff
Remove local clones & make hooks run on merge/edit/upload (#6672)
authorzeripath <art27@cantab.net>
Sat, 11 May 2019 15:29:17 +0000 (16:29 +0100)
committertechknowlogick <hello@techknowlogick.com>
Sat, 11 May 2019 15:29:17 +0000 (11:29 -0400)
* Add options to git.Clone to make it more capable

* Begin the process of removing the local copy and tidy up

* Remove Wiki LocalCopy Checkouts

* Remove the last LocalRepo helpers

* Remove WithTemporaryFile

* Enable push-hooks for these routes

* Ensure tests cope with hooks

Signed-off-by: Andrew Thornton <art27@cantab.net>
* Remove Repository.LocalCopyPath()

* Move temporary repo to use the standard temporary path

* Fix the tests

Signed-off-by: Andrew Thornton <art27@cantab.net>
* Remove LocalWikiPath

* Fix missing remove

Signed-off-by: Andrew Thornton <art27@cantab.net>
* Use AppURL for Oauth user link (#6894)

* Use AppURL for Oauth user link

Fix #6843

* Update oauth.go

* Update oauth.go

* internal/ssh: ignore env command totally (#6825)

* ssh: ignore env command totally

* Remove commented code

Needed fix described in issue #6889

* Escape the commit message on issues update and title in telegram hook (#6901)

* update sdk to latest (#6903)

* improve description of branch protection (fix #6886) (#6906)

The branch protection description text were not quite accurate.

* Fix logging documentation (#6904)

* ENABLE_MACARON_REDIRECT should be REDIRECT_MACARON_LOG

* Allow DISABLE_ROUTER_LOG to be set in the [log] section

* [skip ci] Updated translations via Crowdin

* Move sdk structs to modules/structs (#6905)

* move sdk structs to moduels/structs

* fix tests

* fix fmt

* fix swagger

* fix vendor

34 files changed:
contrib/pr/checkout.go
integrations/api_repo_file_content_test.go
integrations/api_repo_file_create_test.go
integrations/api_repo_file_delete_test.go
integrations/api_repo_file_update_test.go
integrations/editor_test.go
integrations/integration_test.go
integrations/pull_create_test.go
integrations/pull_merge_test.go
integrations/pull_status_test.go
integrations/repo_activity_test.go
integrations/repo_branch_test.go
integrations/repofiles_delete_test.go [new file with mode: 0644]
integrations/repofiles_update_test.go [new file with mode: 0644]
models/helper_directory.go [new file with mode: 0644]
models/helper_environment.go [new file with mode: 0644]
models/pull.go
models/repo.go
models/repo_branch.go
models/repo_test.go
models/user.go
models/wiki.go
models/wiki_test.go
modules/git/command.go
modules/git/repo.go
modules/git/repo_branch.go
modules/git/repo_index.go [new file with mode: 0644]
modules/git/repo_object.go
modules/git/repo_tree.go
modules/repofiles/delete_test.go [deleted file]
modules/repofiles/temp_repo.go
modules/repofiles/update_test.go [deleted file]
modules/setting/repository.go
routers/repo/branch.go

index bc393da135ede0623c61f068816a96bdb6502272..607a503189898c9fd5cc81e2095edfd9a613f26d 100644 (file)
@@ -108,7 +108,6 @@ func runPR() {
        models.LoadFixtures()
        os.RemoveAll(setting.RepoRootPath)
        os.RemoveAll(models.LocalCopyPath())
-       os.RemoveAll(models.LocalWikiPath())
        com.CopyDir(path.Join(curDir, "integrations/gitea-repositories-meta"), setting.RepoRootPath)
 
        log.Printf("[PR] Setting up router\n")
index 1f535ef3a07d910428476850ab602651c6987e23..896d811083fb81db6b5288b78436452222d09b9a 100644 (file)
@@ -6,6 +6,7 @@ package integrations
 
 import (
        "net/http"
+       "net/url"
        "path/filepath"
        "testing"
 
@@ -40,7 +41,10 @@ func getExpectedFileContentResponseForFileContents(branch string) *api.FileConte
 }
 
 func TestAPIGetFileContents(t *testing.T) {
-       prepareTestEnv(t)
+       onGiteaRun(t, testAPIGetFileContents)
+}
+
+func testAPIGetFileContents(t *testing.T, u *url.URL) {
        user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
        user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
        user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
index a43855b06cdc9af77b2146919a01b7f990656510..28097179a060d9ef3f9991544ba3653c495f0bf2 100644 (file)
@@ -8,6 +8,7 @@ import (
        "encoding/base64"
        "fmt"
        "net/http"
+       "net/url"
        "path/filepath"
        "testing"
 
@@ -91,125 +92,126 @@ func getExpectedFileResponseForCreate(commitID, treePath string) *api.FileRespon
 }
 
 func TestAPICreateFile(t *testing.T) {
-       prepareTestEnv(t)
-       user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
-       user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
-       user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
-       repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)   // public repo
-       repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)   // public repo
-       repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo
-       fileID := 0
-
-       // Get user2's token
-       session := loginUser(t, user2.Name)
-       token2 := getTokenForLoggedInUser(t, session)
-       session = emptyTestSession(t)
-       // Get user4's token
-       session = loginUser(t, user4.Name)
-       token4 := getTokenForLoggedInUser(t, session)
-       session = emptyTestSession(t)
-
-       // Test creating a file in repo1 which user2 owns, try both with branch and empty branch
-       for _, branch := range [...]string{
-               "master", // Branch
-               "",       // Empty branch
-       } {
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
+               user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
+               user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
+               repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)   // public repo
+               repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)   // public repo
+               repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo
+               fileID := 0
+
+               // Get user2's token
+               session := loginUser(t, user2.Name)
+               token2 := getTokenForLoggedInUser(t, session)
+               session = emptyTestSession(t)
+               // Get user4's token
+               session = loginUser(t, user4.Name)
+               token4 := getTokenForLoggedInUser(t, session)
+               session = emptyTestSession(t)
+
+               // Test creating a file in repo1 which user2 owns, try both with branch and empty branch
+               for _, branch := range [...]string{
+                       "master", // Branch
+                       "",       // Empty branch
+               } {
+                       createFileOptions := getCreateFileOptions()
+                       createFileOptions.BranchName = branch
+                       fileID++
+                       treePath := fmt.Sprintf("new/file%d.txt", fileID)
+                       url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
+                       req := NewRequestWithJSON(t, "POST", url, &createFileOptions)
+                       resp := session.MakeRequest(t, req, http.StatusCreated)
+                       gitRepo, _ := git.OpenRepository(repo1.RepoPath())
+                       commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName)
+                       expectedFileResponse := getExpectedFileResponseForCreate(commitID, treePath)
+                       var fileResponse api.FileResponse
+                       DecodeJSON(t, resp, &fileResponse)
+                       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)
+               }
+
+               // Test creating a file in a new branch
                createFileOptions := getCreateFileOptions()
-               createFileOptions.BranchName = branch
+               createFileOptions.BranchName = repo1.DefaultBranch
+               createFileOptions.NewBranchName = "new_branch"
                fileID++
                treePath := fmt.Sprintf("new/file%d.txt", fileID)
                url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
                req := NewRequestWithJSON(t, "POST", url, &createFileOptions)
                resp := session.MakeRequest(t, req, http.StatusCreated)
-               gitRepo, _ := git.OpenRepository(repo1.RepoPath())
-               commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName)
-               expectedFileResponse := getExpectedFileResponseForCreate(commitID, treePath)
                var fileResponse api.FileResponse
                DecodeJSON(t, resp, &fileResponse)
-               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)
-       }
+               expectedSHA := "a635aa942442ddfdba07468cf9661c08fbdf0ebf"
+               expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/new/file%d.txt", fileID)
+               expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID)
+               assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
+               assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
+               assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
+
+               // Test trying to create a file that already exists, should fail
+               createFileOptions = getCreateFileOptions()
+               treePath = "README.md"
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
+               resp = session.MakeRequest(t, req, http.StatusInternalServerError)
+               expectedAPIError := context.APIError{
+                       Message: "repository file already exists [path: " + treePath + "]",
+                       URL:     base.DocURL,
+               }
+               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
+               createFileOptions = getCreateFileOptions()
+               fileID++
+               treePath = fmt.Sprintf("new/file%d.txt", fileID)
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4)
+               req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
 
-       // Test creating a file in a new branch
-       createFileOptions := getCreateFileOptions()
-       createFileOptions.BranchName = repo1.DefaultBranch
-       createFileOptions.NewBranchName = "new_branch"
-       fileID++
-       treePath := fmt.Sprintf("new/file%d.txt", fileID)
-       url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
-       req := NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       resp := session.MakeRequest(t, req, http.StatusCreated)
-       var fileResponse api.FileResponse
-       DecodeJSON(t, resp, &fileResponse)
-       expectedSHA := "a635aa942442ddfdba07468cf9661c08fbdf0ebf"
-       expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/new/file%d.txt", fileID)
-       expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID)
-       assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
-       assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
-       assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
-
-       // Test trying to create a file that already exists, should fail
-       createFileOptions = getCreateFileOptions()
-       treePath = "README.md"
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       resp = session.MakeRequest(t, req, http.StatusInternalServerError)
-       expectedAPIError := context.APIError{
-               Message: "repository file already exists [path: " + treePath + "]",
-               URL:     base.DocURL,
-       }
-       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
-       createFileOptions = getCreateFileOptions()
-       fileID++
-       treePath = fmt.Sprintf("new/file%d.txt", fileID)
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4)
-       req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Tests a repo with no token given so will fail
-       createFileOptions = getCreateFileOptions()
-       fileID++
-       treePath = fmt.Sprintf("new/file%d.txt", fileID)
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo16.Name, treePath)
-       req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Test using access token for a private repo that the user of the token owns
-       createFileOptions = getCreateFileOptions()
-       fileID++
-       treePath = fmt.Sprintf("new/file%d.txt", fileID)
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       session.MakeRequest(t, req, http.StatusCreated)
-
-       // Test using org repo "user3/repo3" where user2 is a collaborator
-       createFileOptions = getCreateFileOptions()
-       fileID++
-       treePath = fmt.Sprintf("new/file%d.txt", fileID)
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user3.Name, repo3.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       session.MakeRequest(t, req, http.StatusCreated)
-
-       // Test using org repo "user3/repo3" with no user token
-       createFileOptions = getCreateFileOptions()
-       fileID++
-       treePath = fmt.Sprintf("new/file%d.txt", fileID)
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user3.Name, repo3.Name, treePath)
-       req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Test using repo "user2/repo1" where user4 is a NOT collaborator
-       createFileOptions = getCreateFileOptions()
-       fileID++
-       treePath = fmt.Sprintf("new/file%d.txt", fileID)
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token4)
-       req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-       session.MakeRequest(t, req, http.StatusForbidden)
+               // Tests a repo with no token given so will fail
+               createFileOptions = getCreateFileOptions()
+               fileID++
+               treePath = fmt.Sprintf("new/file%d.txt", fileID)
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo16.Name, treePath)
+               req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Test using access token for a private repo that the user of the token owns
+               createFileOptions = getCreateFileOptions()
+               fileID++
+               treePath = fmt.Sprintf("new/file%d.txt", fileID)
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
+               session.MakeRequest(t, req, http.StatusCreated)
+
+               // Test using org repo "user3/repo3" where user2 is a collaborator
+               createFileOptions = getCreateFileOptions()
+               fileID++
+               treePath = fmt.Sprintf("new/file%d.txt", fileID)
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user3.Name, repo3.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
+               session.MakeRequest(t, req, http.StatusCreated)
+
+               // Test using org repo "user3/repo3" with no user token
+               createFileOptions = getCreateFileOptions()
+               fileID++
+               treePath = fmt.Sprintf("new/file%d.txt", fileID)
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user3.Name, repo3.Name, treePath)
+               req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Test using repo "user2/repo1" where user4 is a NOT collaborator
+               createFileOptions = getCreateFileOptions()
+               fileID++
+               treePath = fmt.Sprintf("new/file%d.txt", fileID)
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token4)
+               req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
+               session.MakeRequest(t, req, http.StatusForbidden)
+       })
 }
index b619f9c43c260696d60afedaad1951beba3f22c5..57e2539e19182e1f3fd8f4aa42e820beab28a22c 100644 (file)
@@ -7,6 +7,7 @@ package integrations
 import (
        "fmt"
        "net/http"
+       "net/url"
        "testing"
 
        "code.gitea.io/gitea/models"
@@ -37,34 +38,50 @@ func getDeleteFileOptions() *api.DeleteFileOptions {
 }
 
 func TestAPIDeleteFile(t *testing.T) {
-       prepareTestEnv(t)
-       user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
-       user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
-       user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
-       repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)   // public repo
-       repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)   // public repo
-       repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo
-       fileID := 0
-
-       // Get user2's token
-       session := loginUser(t, user2.Name)
-       token2 := getTokenForLoggedInUser(t, session)
-       session = emptyTestSession(t)
-       // Get user4's token
-       session = loginUser(t, user4.Name)
-       token4 := getTokenForLoggedInUser(t, session)
-       session = emptyTestSession(t)
-
-       // Test deleting a file in repo1 which user2 owns, try both with branch and empty branch
-       for _, branch := range [...]string{
-               "master", // Branch
-               "",       // Empty branch
-       } {
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
+               user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
+               user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
+               repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)   // public repo
+               repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)   // public repo
+               repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo
+               fileID := 0
+
+               // Get user2's token
+               session := loginUser(t, user2.Name)
+               token2 := getTokenForLoggedInUser(t, session)
+               session = emptyTestSession(t)
+               // Get user4's token
+               session = loginUser(t, user4.Name)
+               token4 := getTokenForLoggedInUser(t, session)
+               session = emptyTestSession(t)
+
+               // Test deleting a file in repo1 which user2 owns, try both with branch and empty branch
+               for _, branch := range [...]string{
+                       "master", // Branch
+                       "",       // Empty branch
+               } {
+                       fileID++
+                       treePath := fmt.Sprintf("delete/file%d.txt", fileID)
+                       createFile(user2, repo1, treePath)
+                       deleteFileOptions := getDeleteFileOptions()
+                       deleteFileOptions.BranchName = branch
+                       url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
+                       req := NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+                       resp := session.MakeRequest(t, req, http.StatusOK)
+                       var fileResponse api.FileResponse
+                       DecodeJSON(t, resp, &fileResponse)
+                       assert.NotNil(t, fileResponse)
+                       assert.Nil(t, fileResponse.Content)
+               }
+
+               // Test deleting file and making the delete in a new branch
                fileID++
                treePath := fmt.Sprintf("delete/file%d.txt", fileID)
                createFile(user2, repo1, treePath)
                deleteFileOptions := getDeleteFileOptions()
-               deleteFileOptions.BranchName = branch
+               deleteFileOptions.BranchName = repo1.DefaultBranch
+               deleteFileOptions.NewBranchName = "new_branch"
                url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
                req := NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
                resp := session.MakeRequest(t, req, http.StatusOK)
@@ -72,92 +89,77 @@ func TestAPIDeleteFile(t *testing.T) {
                DecodeJSON(t, resp, &fileResponse)
                assert.NotNil(t, fileResponse)
                assert.Nil(t, fileResponse.Content)
-       }
 
-       // Test deleting file and making the delete in a new branch
-       fileID++
-       treePath := fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user2, repo1, treePath)
-       deleteFileOptions := getDeleteFileOptions()
-       deleteFileOptions.BranchName = repo1.DefaultBranch
-       deleteFileOptions.NewBranchName = "new_branch"
-       url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
-       req := NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       resp := session.MakeRequest(t, req, http.StatusOK)
-       var fileResponse api.FileResponse
-       DecodeJSON(t, resp, &fileResponse)
-       assert.NotNil(t, fileResponse)
-       assert.Nil(t, fileResponse.Content)
-
-       // Test deleting a file with the wrong SHA
-       fileID++
-       treePath = fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user2, repo1, treePath)
-       deleteFileOptions = getDeleteFileOptions()
-       correctSHA := deleteFileOptions.SHA
-       deleteFileOptions.SHA = "badsha"
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       resp = session.MakeRequest(t, req, http.StatusInternalServerError)
-       expectedAPIError := context.APIError{
-               Message: "sha does not match [given: " + deleteFileOptions.SHA + ", expected: " + correctSHA + "]",
-               URL:     base.DocURL,
-       }
-       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++
-       treePath = fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user2, repo16, treePath)
-       deleteFileOptions = getDeleteFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4)
-       req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Tests a repo with no token given so will fail
-       fileID++
-       treePath = fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user2, repo16, treePath)
-       deleteFileOptions = getDeleteFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo16.Name, treePath)
-       req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Test using access token for a private repo that the user of the token owns
-       fileID++
-       treePath = fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user2, repo16, treePath)
-       deleteFileOptions = getDeleteFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       session.MakeRequest(t, req, http.StatusOK)
-
-       // Test using org repo "user3/repo3" where user2 is a collaborator
-       fileID++
-       treePath = fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user3, repo3, treePath)
-       deleteFileOptions = getDeleteFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user3.Name, repo3.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       session.MakeRequest(t, req, http.StatusOK)
-
-       // Test using org repo "user3/repo3" with no user token
-       fileID++
-       treePath = fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user3, repo3, treePath)
-       deleteFileOptions = getDeleteFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user3.Name, repo3.Name, treePath)
-       req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Test using repo "user2/repo1" where user4 is a NOT collaborator
-       fileID++
-       treePath = fmt.Sprintf("delete/file%d.txt", fileID)
-       createFile(user2, repo1, treePath)
-       deleteFileOptions = getDeleteFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token4)
-       req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
-       session.MakeRequest(t, req, http.StatusForbidden)
+               // Test deleting a file with the wrong SHA
+               fileID++
+               treePath = fmt.Sprintf("delete/file%d.txt", fileID)
+               createFile(user2, repo1, treePath)
+               deleteFileOptions = getDeleteFileOptions()
+               correctSHA := deleteFileOptions.SHA
+               deleteFileOptions.SHA = "badsha"
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+               resp = session.MakeRequest(t, req, http.StatusInternalServerError)
+               expectedAPIError := context.APIError{
+                       Message: "sha does not match [given: " + deleteFileOptions.SHA + ", expected: " + correctSHA + "]",
+                       URL:     base.DocURL,
+               }
+               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++
+               treePath = fmt.Sprintf("delete/file%d.txt", fileID)
+               createFile(user2, repo16, treePath)
+               deleteFileOptions = getDeleteFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4)
+               req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Tests a repo with no token given so will fail
+               fileID++
+               treePath = fmt.Sprintf("delete/file%d.txt", fileID)
+               createFile(user2, repo16, treePath)
+               deleteFileOptions = getDeleteFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo16.Name, treePath)
+               req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Test using access token for a private repo that the user of the token owns
+               fileID++
+               treePath = fmt.Sprintf("delete/file%d.txt", fileID)
+               createFile(user2, repo16, treePath)
+               deleteFileOptions = getDeleteFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+               session.MakeRequest(t, req, http.StatusOK)
+
+               // Test using org repo "user3/repo3" where user2 is a collaborator
+               fileID++
+               treePath = fmt.Sprintf("delete/file%d.txt", fileID)
+               createFile(user3, repo3, treePath)
+               deleteFileOptions = getDeleteFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user3.Name, repo3.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+               session.MakeRequest(t, req, http.StatusOK)
+
+               // Test using org repo "user3/repo3" with no user token
+               fileID++
+               treePath = fmt.Sprintf("delete/file%d.txt", fileID)
+               createFile(user3, repo3, treePath)
+               deleteFileOptions = getDeleteFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user3.Name, repo3.Name, treePath)
+               req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Test using repo "user2/repo1" where user4 is a NOT collaborator
+               fileID++
+               treePath = fmt.Sprintf("delete/file%d.txt", fileID)
+               createFile(user2, repo1, treePath)
+               deleteFileOptions = getDeleteFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token4)
+               req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions)
+               session.MakeRequest(t, req, http.StatusForbidden)
+       })
 }
index 71994564ffce22b5330cd14c4f095ee493f8dd40..37438339bbd318eb4ecccf6d7ea8fe924bf5632e 100644 (file)
@@ -8,6 +8,7 @@ import (
        "encoding/base64"
        "fmt"
        "net/http"
+       "net/url"
        "path/filepath"
        "testing"
 
@@ -79,156 +80,157 @@ func getExpectedFileResponseForUpdate(commitID, treePath string) *api.FileRespon
 }
 
 func TestAPIUpdateFile(t *testing.T) {
-       prepareTestEnv(t)
-       user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
-       user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
-       user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
-       repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)   // public repo
-       repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)   // public repo
-       repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo
-       fileID := 0
-
-       // Get user2's token
-       session := loginUser(t, user2.Name)
-       token2 := getTokenForLoggedInUser(t, session)
-       session = emptyTestSession(t)
-       // Get user4's token
-       session = loginUser(t, user4.Name)
-       token4 := getTokenForLoggedInUser(t, session)
-       session = emptyTestSession(t)
-
-       // Test updating a file in repo1 which user2 owns, try both with branch and empty branch
-       for _, branch := range [...]string{
-               "master", // Branch
-               "",       // Empty branch
-       } {
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)               // owner of the repo1 & repo16
+               user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)               // owner of the repo3, is an org
+               user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)               // owner of neither repos
+               repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)   // public repo
+               repo3 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)   // public repo
+               repo16 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 16}).(*models.Repository) // private repo
+               fileID := 0
+
+               // Get user2's token
+               session := loginUser(t, user2.Name)
+               token2 := getTokenForLoggedInUser(t, session)
+               session = emptyTestSession(t)
+               // Get user4's token
+               session = loginUser(t, user4.Name)
+               token4 := getTokenForLoggedInUser(t, session)
+               session = emptyTestSession(t)
+
+               // Test updating a file in repo1 which user2 owns, try both with branch and empty branch
+               for _, branch := range [...]string{
+                       "master", // Branch
+                       "",       // Empty branch
+               } {
+                       fileID++
+                       treePath := fmt.Sprintf("update/file%d.txt", fileID)
+                       createFile(user2, repo1, treePath)
+                       updateFileOptions := getUpdateFileOptions()
+                       updateFileOptions.BranchName = branch
+                       url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
+                       req := NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+                       resp := session.MakeRequest(t, req, http.StatusOK)
+                       gitRepo, _ := git.OpenRepository(repo1.RepoPath())
+                       commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName)
+                       expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath)
+                       var fileResponse api.FileResponse
+                       DecodeJSON(t, resp, &fileResponse)
+                       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)
+               }
+
+               // Test updating a file in a new branch
+               updateFileOptions := getUpdateFileOptions()
+               updateFileOptions.BranchName = repo1.DefaultBranch
+               updateFileOptions.NewBranchName = "new_branch"
                fileID++
                treePath := fmt.Sprintf("update/file%d.txt", fileID)
                createFile(user2, repo1, treePath)
-               updateFileOptions := getUpdateFileOptions()
-               updateFileOptions.BranchName = branch
                url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
                req := NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
                resp := session.MakeRequest(t, req, http.StatusOK)
-               gitRepo, _ := git.OpenRepository(repo1.RepoPath())
-               commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName)
-               expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath)
                var fileResponse api.FileResponse
                DecodeJSON(t, resp, &fileResponse)
-               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)
-       }
-
-       // Test updating a file in a new branch
-       updateFileOptions := getUpdateFileOptions()
-       updateFileOptions.BranchName = repo1.DefaultBranch
-       updateFileOptions.NewBranchName = "new_branch"
-       fileID++
-       treePath := fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user2, repo1, treePath)
-       url := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
-       req := NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       resp := session.MakeRequest(t, req, http.StatusOK)
-       var fileResponse api.FileResponse
-       DecodeJSON(t, resp, &fileResponse)
-       expectedSHA := "08bd14b2e2852529157324de9c226b3364e76136"
-       expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/update/file%d.txt", fileID)
-       expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID)
-       assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
-       assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
-       assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
-
-       // Test updating a file and renaming it
-       updateFileOptions = getUpdateFileOptions()
-       updateFileOptions.BranchName = repo1.DefaultBranch
-       fileID++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user2, repo1, treePath)
-       updateFileOptions.FromPath = treePath
-       treePath = "rename/" + treePath
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       DecodeJSON(t, resp, &fileResponse)
-       expectedSHA = "08bd14b2e2852529157324de9c226b3364e76136"
-       expectedHTMLURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/master/rename/update/file%d.txt", fileID)
-       expectedDownloadURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID)
-       assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
-       assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
-       assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
-
-       // Test updating a file with the wrong SHA
-       fileID++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user2, repo1, treePath)
-       updateFileOptions = getUpdateFileOptions()
-       correctSHA := updateFileOptions.SHA
-       updateFileOptions.SHA = "badsha"
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       resp = session.MakeRequest(t, req, http.StatusInternalServerError)
-       expectedAPIError := context.APIError{
-               Message: "sha does not match [given: " + updateFileOptions.SHA + ", expected: " + correctSHA + "]",
-               URL:     base.DocURL,
-       }
-       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++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user2, repo16, treePath)
-       updateFileOptions = getUpdateFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Tests a repo with no token given so will fail
-       fileID++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user2, repo16, treePath)
-       updateFileOptions = getUpdateFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo16.Name, treePath)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Test using access token for a private repo that the user of the token owns
-       fileID++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user2, repo16, treePath)
-       updateFileOptions = getUpdateFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       session.MakeRequest(t, req, http.StatusOK)
-
-       // Test using org repo "user3/repo3" where user2 is a collaborator
-       fileID++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user3, repo3, treePath)
-       updateFileOptions = getUpdateFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user3.Name, repo3.Name, treePath, token2)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       session.MakeRequest(t, req, http.StatusOK)
-
-       // Test using org repo "user3/repo3" with no user token
-       fileID++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user3, repo3, treePath)
-       updateFileOptions = getUpdateFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user3.Name, repo3.Name, treePath)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       session.MakeRequest(t, req, http.StatusNotFound)
-
-       // Test using repo "user2/repo1" where user4 is a NOT collaborator
-       fileID++
-       treePath = fmt.Sprintf("update/file%d.txt", fileID)
-       createFile(user2, repo1, treePath)
-       updateFileOptions = getUpdateFileOptions()
-       url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token4)
-       req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-       session.MakeRequest(t, req, http.StatusForbidden)
+               expectedSHA := "08bd14b2e2852529157324de9c226b3364e76136"
+               expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/update/file%d.txt", fileID)
+               expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID)
+               assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
+               assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
+               assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
+
+               // Test updating a file and renaming it
+               updateFileOptions = getUpdateFileOptions()
+               updateFileOptions.BranchName = repo1.DefaultBranch
+               fileID++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user2, repo1, treePath)
+               updateFileOptions.FromPath = treePath
+               treePath = "rename/" + treePath
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               DecodeJSON(t, resp, &fileResponse)
+               expectedSHA = "08bd14b2e2852529157324de9c226b3364e76136"
+               expectedHTMLURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/master/rename/update/file%d.txt", fileID)
+               expectedDownloadURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID)
+               assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
+               assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
+               assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
+
+               // Test updating a file with the wrong SHA
+               fileID++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user2, repo1, treePath)
+               updateFileOptions = getUpdateFileOptions()
+               correctSHA := updateFileOptions.SHA
+               updateFileOptions.SHA = "badsha"
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               resp = session.MakeRequest(t, req, http.StatusInternalServerError)
+               expectedAPIError := context.APIError{
+                       Message: "sha does not match [given: " + updateFileOptions.SHA + ", expected: " + correctSHA + "]",
+                       URL:     base.DocURL,
+               }
+               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++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user2, repo16, treePath)
+               updateFileOptions = getUpdateFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Tests a repo with no token given so will fail
+               fileID++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user2, repo16, treePath)
+               updateFileOptions = getUpdateFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo16.Name, treePath)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Test using access token for a private repo that the user of the token owns
+               fileID++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user2, repo16, treePath)
+               updateFileOptions = getUpdateFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               session.MakeRequest(t, req, http.StatusOK)
+
+               // Test using org repo "user3/repo3" where user2 is a collaborator
+               fileID++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user3, repo3, treePath)
+               updateFileOptions = getUpdateFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user3.Name, repo3.Name, treePath, token2)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               session.MakeRequest(t, req, http.StatusOK)
+
+               // Test using org repo "user3/repo3" with no user token
+               fileID++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user3, repo3, treePath)
+               updateFileOptions = getUpdateFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user3.Name, repo3.Name, treePath)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               session.MakeRequest(t, req, http.StatusNotFound)
+
+               // Test using repo "user2/repo1" where user4 is a NOT collaborator
+               fileID++
+               treePath = fmt.Sprintf("update/file%d.txt", fileID)
+               createFile(user2, repo1, treePath)
+               updateFileOptions = getUpdateFileOptions()
+               url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token4)
+               req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
+               session.MakeRequest(t, req, http.StatusForbidden)
+       })
 }
index e2dd2e1dc4b87ba7274e8688631d3d852c065b50..8e6effe7ebd8df247263ce4ca733b8936c7bb27d 100644 (file)
@@ -7,6 +7,7 @@ package integrations
 import (
        "net/http"
        "net/http/httptest"
+       "net/url"
        "path"
        "testing"
 
@@ -14,80 +15,79 @@ import (
 )
 
 func TestCreateFile(t *testing.T) {
-       prepareTestEnv(t)
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               session := loginUser(t, "user2")
 
-       session := loginUser(t, "user2")
+               // Request editor page
+               req := NewRequest(t, "GET", "/user2/repo1/_new/master/")
+               resp := session.MakeRequest(t, req, http.StatusOK)
 
-       // Request editor page
-       req := NewRequest(t, "GET", "/user2/repo1/_new/master/")
-       resp := session.MakeRequest(t, req, http.StatusOK)
-
-       doc := NewHTMLParser(t, resp.Body)
-       lastCommit := doc.GetInputValueByName("last_commit")
-       assert.NotEmpty(t, lastCommit)
+               doc := NewHTMLParser(t, resp.Body)
+               lastCommit := doc.GetInputValueByName("last_commit")
+               assert.NotEmpty(t, lastCommit)
 
-       // Save new file to master branch
-       req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{
-               "_csrf":         doc.GetCSRF(),
-               "last_commit":   lastCommit,
-               "tree_path":     "test.txt",
-               "content":       "Content",
-               "commit_choice": "direct",
+               // Save new file to master branch
+               req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{
+                       "_csrf":         doc.GetCSRF(),
+                       "last_commit":   lastCommit,
+                       "tree_path":     "test.txt",
+                       "content":       "Content",
+                       "commit_choice": "direct",
+               })
+               resp = session.MakeRequest(t, req, http.StatusFound)
        })
-       resp = session.MakeRequest(t, req, http.StatusFound)
 }
 
 func TestCreateFileOnProtectedBranch(t *testing.T) {
-       prepareTestEnv(t)
-
-       session := loginUser(t, "user2")
-
-       csrf := GetCSRF(t, session, "/user2/repo1/settings/branches")
-       // Change master branch to protected
-       req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/master", map[string]string{
-               "_csrf":     csrf,
-               "protected": "on",
-       })
-       resp := session.MakeRequest(t, req, http.StatusFound)
-       // Check if master branch has been locked successfully
-       flashCookie := session.GetCookie("macaron_flash")
-       assert.NotNil(t, flashCookie)
-       assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Bbranch%2B%2527master%2527%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value)
-
-       // Request editor page
-       req = NewRequest(t, "GET", "/user2/repo1/_new/master/")
-       resp = session.MakeRequest(t, req, http.StatusOK)
-
-       doc := NewHTMLParser(t, resp.Body)
-       lastCommit := doc.GetInputValueByName("last_commit")
-       assert.NotEmpty(t, lastCommit)
-
-       // Save new file to master branch
-       req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{
-               "_csrf":         doc.GetCSRF(),
-               "last_commit":   lastCommit,
-               "tree_path":     "test.txt",
-               "content":       "Content",
-               "commit_choice": "direct",
-       })
-
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       // Check body for error message
-       assert.Contains(t, resp.Body.String(), "Cannot commit to protected branch &#39;master&#39;.")
-
-       // remove the protected branch
-       csrf = GetCSRF(t, session, "/user2/repo1/settings/branches")
-       // Change master branch to protected
-       req = NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/master", map[string]string{
-               "_csrf":     csrf,
-               "protected": "off",
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               session := loginUser(t, "user2")
+
+               csrf := GetCSRF(t, session, "/user2/repo1/settings/branches")
+               // Change master branch to protected
+               req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/master", map[string]string{
+                       "_csrf":     csrf,
+                       "protected": "on",
+               })
+               resp := session.MakeRequest(t, req, http.StatusFound)
+               // Check if master branch has been locked successfully
+               flashCookie := session.GetCookie("macaron_flash")
+               assert.NotNil(t, flashCookie)
+               assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Bbranch%2B%2527master%2527%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value)
+
+               // Request editor page
+               req = NewRequest(t, "GET", "/user2/repo1/_new/master/")
+               resp = session.MakeRequest(t, req, http.StatusOK)
+
+               doc := NewHTMLParser(t, resp.Body)
+               lastCommit := doc.GetInputValueByName("last_commit")
+               assert.NotEmpty(t, lastCommit)
+
+               // Save new file to master branch
+               req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{
+                       "_csrf":         doc.GetCSRF(),
+                       "last_commit":   lastCommit,
+                       "tree_path":     "test.txt",
+                       "content":       "Content",
+                       "commit_choice": "direct",
+               })
+
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               // Check body for error message
+               assert.Contains(t, resp.Body.String(), "Cannot commit to protected branch &#39;master&#39;.")
+
+               // remove the protected branch
+               csrf = GetCSRF(t, session, "/user2/repo1/settings/branches")
+               // Change master branch to protected
+               req = NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/master", map[string]string{
+                       "_csrf":     csrf,
+                       "protected": "off",
+               })
+               resp = session.MakeRequest(t, req, http.StatusFound)
+               // Check if master branch has been locked successfully
+               flashCookie = session.GetCookie("macaron_flash")
+               assert.NotNil(t, flashCookie)
+               assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Bbranch%2B%2527master%2527%2Bhas%2Bbeen%2Bdisabled.", flashCookie.Value)
        })
-       resp = session.MakeRequest(t, req, http.StatusFound)
-       // Check if master branch has been locked successfully
-       flashCookie = session.GetCookie("macaron_flash")
-       assert.NotNil(t, flashCookie)
-       assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Bbranch%2B%2527master%2527%2Bhas%2Bbeen%2Bdisabled.", flashCookie.Value)
-
 }
 
 func testEditFile(t *testing.T, session *TestSession, user, repo, branch, filePath, newContent string) *httptest.ResponseRecorder {
@@ -151,13 +151,15 @@ func testEditFileToNewBranch(t *testing.T, session *TestSession, user, repo, bra
 }
 
 func TestEditFile(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user2")
-       testEditFile(t, session, "user2", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               session := loginUser(t, "user2")
+               testEditFile(t, session, "user2", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+       })
 }
 
 func TestEditFileToNewBranch(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user2")
-       testEditFileToNewBranch(t, session, "user2", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n")
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               session := loginUser(t, "user2")
+               testEditFileToNewBranch(t, session, "user2", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n")
+       })
 }
index 566859518a10b6f191bc94bf3233be46c33bf833..93dacaf78af21f94167dcea0d1cc7dbdf815a61b 100644 (file)
@@ -178,7 +178,6 @@ func prepareTestEnv(t testing.TB, skip ...int) {
        assert.NoError(t, models.LoadFixtures())
        assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
        assert.NoError(t, os.RemoveAll(models.LocalCopyPath()))
-       assert.NoError(t, os.RemoveAll(models.LocalWikiPath()))
 
        assert.NoError(t, com.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"),
                setting.RepoRootPath))
index ed553bf162e9dd5060e95858f4d83d2a55e99d63..8f39e8b02871550e8c9d4f3a16e26040a7d886ae 100644 (file)
@@ -7,6 +7,7 @@ package integrations
 import (
        "net/http"
        "net/http/httptest"
+       "net/url"
        "path"
        "strings"
        "testing"
@@ -43,63 +44,65 @@ func testPullCreate(t *testing.T, session *TestSession, user, repo, branch, titl
 }
 
 func TestPullCreate(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
-
-       // check the redirected URL
-       url := resp.HeaderMap.Get("Location")
-       assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url)
-
-       // check .diff can be accessed and matches performed change
-       req := NewRequest(t, "GET", url+".diff")
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       assert.Regexp(t, `\+Hello, World \(Edited\)`, resp.Body)
-       assert.Regexp(t, "^diff", resp.Body)
-       assert.NotRegexp(t, "diff.*diff", resp.Body) // not two diffs, just one
-
-       // check .patch can be accessed and matches performed change
-       req = NewRequest(t, "GET", url+".patch")
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       assert.Regexp(t, `\+Hello, World \(Edited\)`, resp.Body)
-       assert.Regexp(t, "diff", resp.Body)
-       assert.Regexp(t, `Subject: \[PATCH\] Update 'README.md'`, resp.Body)
-       assert.NotRegexp(t, "diff.*diff", resp.Body) // not two diffs, just one
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
+
+               // check the redirected URL
+               url := resp.HeaderMap.Get("Location")
+               assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url)
+
+               // check .diff can be accessed and matches performed change
+               req := NewRequest(t, "GET", url+".diff")
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               assert.Regexp(t, `\+Hello, World \(Edited\)`, resp.Body)
+               assert.Regexp(t, "^diff", resp.Body)
+               assert.NotRegexp(t, "diff.*diff", resp.Body) // not two diffs, just one
+
+               // check .patch can be accessed and matches performed change
+               req = NewRequest(t, "GET", url+".patch")
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               assert.Regexp(t, `\+Hello, World \(Edited\)`, resp.Body)
+               assert.Regexp(t, "diff", resp.Body)
+               assert.Regexp(t, `Subject: \[PATCH\] Update 'README.md'`, resp.Body)
+               assert.NotRegexp(t, "diff.*diff", resp.Body) // not two diffs, just one
+       })
 }
 
 func TestPullCreate_TitleEscape(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "<i>XSS PR</i>")
-
-       // check the redirected URL
-       url := resp.HeaderMap.Get("Location")
-       assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url)
-
-       // Edit title
-       req := NewRequest(t, "GET", url)
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       htmlDoc := NewHTMLParser(t, resp.Body)
-       editTestTitleURL, exists := htmlDoc.doc.Find("#save-edit-title").First().Attr("data-update-url")
-       assert.True(t, exists, "The template has changed")
-
-       req = NewRequestWithValues(t, "POST", editTestTitleURL, map[string]string{
-               "_csrf": htmlDoc.GetCSRF(),
-               "title": "<u>XSS PR</u>",
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "<i>XSS PR</i>")
+
+               // check the redirected URL
+               url := resp.HeaderMap.Get("Location")
+               assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url)
+
+               // Edit title
+               req := NewRequest(t, "GET", url)
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               htmlDoc := NewHTMLParser(t, resp.Body)
+               editTestTitleURL, exists := htmlDoc.doc.Find("#save-edit-title").First().Attr("data-update-url")
+               assert.True(t, exists, "The template has changed")
+
+               req = NewRequestWithValues(t, "POST", editTestTitleURL, map[string]string{
+                       "_csrf": htmlDoc.GetCSRF(),
+                       "title": "<u>XSS PR</u>",
+               })
+               session.MakeRequest(t, req, http.StatusOK)
+
+               req = NewRequest(t, "GET", url)
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               htmlDoc = NewHTMLParser(t, resp.Body)
+               titleHTML, err := htmlDoc.doc.Find(".comments .event .text b").First().Html()
+               assert.NoError(t, err)
+               assert.Equal(t, "&lt;i&gt;XSS PR&lt;/i&gt;", titleHTML)
+               titleHTML, err = htmlDoc.doc.Find(".comments .event .text b").Next().Html()
+               assert.NoError(t, err)
+               assert.Equal(t, "&lt;u&gt;XSS PR&lt;/u&gt;", titleHTML)
        })
-       session.MakeRequest(t, req, http.StatusOK)
-
-       req = NewRequest(t, "GET", url)
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       htmlDoc = NewHTMLParser(t, resp.Body)
-       titleHTML, err := htmlDoc.doc.Find(".comments .event .text b").First().Html()
-       assert.NoError(t, err)
-       assert.Equal(t, "&lt;i&gt;XSS PR&lt;/i&gt;", titleHTML)
-       titleHTML, err = htmlDoc.doc.Find(".comments .event .text b").Next().Html()
-       assert.NoError(t, err)
-       assert.Equal(t, "&lt;u&gt;XSS PR&lt;/u&gt;", titleHTML)
 }
index f466515eb40843fda462dd16476102ca48d300f1..1f0ad27a0b5b953d891e23da82a20372c0578986 100644 (file)
@@ -7,6 +7,7 @@ package integrations
 import (
        "net/http"
        "net/http/httptest"
+       "net/url"
        "path"
        "strings"
        "testing"
@@ -52,108 +53,118 @@ func testPullCleanUp(t *testing.T, session *TestSession, user, repo, pullnum str
 }
 
 func TestPullMerge(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+       onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
 
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
 
-       elem := strings.Split(test.RedirectURL(resp), "/")
-       assert.EqualValues(t, "pulls", elem[3])
-       testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
+               elem := strings.Split(test.RedirectURL(resp), "/")
+               assert.EqualValues(t, "pulls", elem[3])
+               testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
+       })
 }
 
 func TestPullRebase(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+       onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
 
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
 
-       elem := strings.Split(test.RedirectURL(resp), "/")
-       assert.EqualValues(t, "pulls", elem[3])
-       testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebase)
+               elem := strings.Split(test.RedirectURL(resp), "/")
+               assert.EqualValues(t, "pulls", elem[3])
+               testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebase)
+       })
 }
 
 func TestPullRebaseMerge(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+       onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+               prepareTestEnv(t)
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
 
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
 
-       elem := strings.Split(test.RedirectURL(resp), "/")
-       assert.EqualValues(t, "pulls", elem[3])
-       testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebaseMerge)
+               elem := strings.Split(test.RedirectURL(resp), "/")
+               assert.EqualValues(t, "pulls", elem[3])
+               testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebaseMerge)
+       })
 }
 
 func TestPullSquash(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited!)\n")
-
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
-
-       elem := strings.Split(test.RedirectURL(resp), "/")
-       assert.EqualValues(t, "pulls", elem[3])
-       testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleSquash)
+       onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+               prepareTestEnv(t)
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited!)\n")
+
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
+
+               elem := strings.Split(test.RedirectURL(resp), "/")
+               assert.EqualValues(t, "pulls", elem[3])
+               testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleSquash)
+       })
 }
 
 func TestPullCleanUpAfterMerge(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n")
+       onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+               prepareTestEnv(t)
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n")
 
-       resp := testPullCreate(t, session, "user1", "repo1", "feature/test", "This is a pull title")
+               resp := testPullCreate(t, session, "user1", "repo1", "feature/test", "This is a pull title")
 
-       elem := strings.Split(test.RedirectURL(resp), "/")
-       assert.EqualValues(t, "pulls", elem[3])
-       testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
+               elem := strings.Split(test.RedirectURL(resp), "/")
+               assert.EqualValues(t, "pulls", elem[3])
+               testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
 
-       // Check PR branch deletion
-       resp = testPullCleanUp(t, session, elem[1], elem[2], elem[4])
-       respJSON := struct {
-               Redirect string
-       }{}
-       DecodeJSON(t, resp, &respJSON)
+               // Check PR branch deletion
+               resp = testPullCleanUp(t, session, elem[1], elem[2], elem[4])
+               respJSON := struct {
+                       Redirect string
+               }{}
+               DecodeJSON(t, resp, &respJSON)
 
-       assert.NotEmpty(t, respJSON.Redirect, "Redirected URL is not found")
+               assert.NotEmpty(t, respJSON.Redirect, "Redirected URL is not found")
 
-       elem = strings.Split(respJSON.Redirect, "/")
-       assert.EqualValues(t, "pulls", elem[3])
+               elem = strings.Split(respJSON.Redirect, "/")
+               assert.EqualValues(t, "pulls", elem[3])
 
-       // Check branch deletion result
-       req := NewRequest(t, "GET", respJSON.Redirect)
-       resp = session.MakeRequest(t, req, http.StatusOK)
+               // Check branch deletion result
+               req := NewRequest(t, "GET", respJSON.Redirect)
+               resp = session.MakeRequest(t, req, http.StatusOK)
 
-       htmlDoc := NewHTMLParser(t, resp.Body)
-       resultMsg := htmlDoc.doc.Find(".ui.message>p").Text()
+               htmlDoc := NewHTMLParser(t, resp.Body)
+               resultMsg := htmlDoc.doc.Find(".ui.message>p").Text()
 
-       assert.EqualValues(t, "Branch 'user1/feature/test' has been deleted.", resultMsg)
+               assert.EqualValues(t, "Branch 'user1/feature/test' has been deleted.", resultMsg)
+       })
 }
 
 func TestCantMergeWorkInProgress(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
-
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "[wip] This is a pull title")
-
-       req := NewRequest(t, "GET", resp.Header().Get("Location"))
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       htmlDoc := NewHTMLParser(t, resp.Body)
-       text := strings.TrimSpace(htmlDoc.doc.Find(".merge.segment > .text.grey").Text())
-       assert.NotEmpty(t, text, "Can't find WIP text")
-
-       // remove <strong /> from lang
-       expected := i18n.Tr("en", "repo.pulls.cannot_merge_work_in_progress", "[wip]")
-       replacer := strings.NewReplacer("<strong>", "", "</strong>", "")
-       assert.Equal(t, replacer.Replace(expected), text, "Unable to find WIP text")
+       onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+               prepareTestEnv(t)
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "[wip] This is a pull title")
+
+               req := NewRequest(t, "GET", resp.Header().Get("Location"))
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               htmlDoc := NewHTMLParser(t, resp.Body)
+               text := strings.TrimSpace(htmlDoc.doc.Find(".merge.segment > .text.grey").Text())
+               assert.NotEmpty(t, text, "Can't find WIP text")
+
+               // remove <strong /> from lang
+               expected := i18n.Tr("en", "repo.pulls.cannot_merge_work_in_progress", "[wip]")
+               replacer := strings.NewReplacer("<strong>", "", "</strong>", "")
+               assert.Equal(t, replacer.Replace(expected), text, "Unable to find WIP text")
+       })
 }
index 2381444676ebfeffc46d98e2c1257c4de15c4a43..2a4d8e0b68fa4a76c97b8b6fa308645883d39051 100644 (file)
@@ -6,6 +6,7 @@ package integrations
 import (
        "fmt"
        "net/http"
+       "net/url"
        "path"
        "testing"
 
@@ -16,78 +17,79 @@ import (
 )
 
 func TestPullCreate_CommitStatus(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFileToNewBranch(t, session, "user1", "repo1", "master", "status1", "README.md", "status1")
-
-       url := path.Join("user1", "repo1", "compare", "master...status1")
-       req := NewRequestWithValues(t, "POST", url,
-               map[string]string{
-                       "_csrf": GetCSRF(t, session, url),
-                       "title": "pull request from status1",
-               },
-       )
-       session.MakeRequest(t, req, http.StatusFound)
-
-       req = NewRequest(t, "GET", "/user1/repo1/pulls")
-       resp := session.MakeRequest(t, req, http.StatusOK)
-       doc := NewHTMLParser(t, resp.Body)
-
-       // Request repository commits page
-       req = NewRequest(t, "GET", "/user1/repo1/pulls/1/commits")
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       doc = NewHTMLParser(t, resp.Body)
-
-       // Get first commit URL
-       commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
-       assert.True(t, exists)
-       assert.NotEmpty(t, commitURL)
-
-       commitID := path.Base(commitURL)
-
-       statusList := []models.CommitStatusState{
-               models.CommitStatusPending,
-               models.CommitStatusError,
-               models.CommitStatusFailure,
-               models.CommitStatusWarning,
-               models.CommitStatusSuccess,
-       }
-
-       statesIcons := map[models.CommitStatusState]string{
-               models.CommitStatusPending: "circle icon yellow",
-               models.CommitStatusSuccess: "check icon green",
-               models.CommitStatusError:   "warning icon red",
-               models.CommitStatusFailure: "remove icon red",
-               models.CommitStatusWarning: "warning sign icon yellow",
-       }
-
-       // Update commit status, and check if icon is updated as well
-       for _, status := range statusList {
-
-               // Call API to add status for commit
-               token := getTokenForLoggedInUser(t, session)
-               req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/user1/repo1/statuses/%s?token=%s", commitID, token),
-                       api.CreateStatusOption{
-                               State:       api.StatusState(status),
-                               TargetURL:   "http://test.ci/",
-                               Description: "",
-                               Context:     "testci",
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               session := loginUser(t, "user1")
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFileToNewBranch(t, session, "user1", "repo1", "master", "status1", "README.md", "status1")
+
+               url := path.Join("user1", "repo1", "compare", "master...status1")
+               req := NewRequestWithValues(t, "POST", url,
+                       map[string]string{
+                               "_csrf": GetCSRF(t, session, url),
+                               "title": "pull request from status1",
                        },
                )
-               session.MakeRequest(t, req, http.StatusCreated)
+               session.MakeRequest(t, req, http.StatusFound)
 
-               req = NewRequestf(t, "GET", "/user1/repo1/pulls/1/commits")
+               req = NewRequest(t, "GET", "/user1/repo1/pulls")
+               resp := session.MakeRequest(t, req, http.StatusOK)
+               doc := NewHTMLParser(t, resp.Body)
+
+               // Request repository commits page
+               req = NewRequest(t, "GET", "/user1/repo1/pulls/1/commits")
                resp = session.MakeRequest(t, req, http.StatusOK)
                doc = NewHTMLParser(t, resp.Body)
 
-               commitURL, exists = doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
+               // Get first commit URL
+               commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
                assert.True(t, exists)
                assert.NotEmpty(t, commitURL)
-               assert.EqualValues(t, commitID, path.Base(commitURL))
 
-               cls, ok := doc.doc.Find("#commits-table tbody tr td.message i.commit-status").Last().Attr("class")
-               assert.True(t, ok)
-               assert.EqualValues(t, "commit-status "+statesIcons[status], cls)
-       }
+               commitID := path.Base(commitURL)
+
+               statusList := []models.CommitStatusState{
+                       models.CommitStatusPending,
+                       models.CommitStatusError,
+                       models.CommitStatusFailure,
+                       models.CommitStatusWarning,
+                       models.CommitStatusSuccess,
+               }
+
+               statesIcons := map[models.CommitStatusState]string{
+                       models.CommitStatusPending: "circle icon yellow",
+                       models.CommitStatusSuccess: "check icon green",
+                       models.CommitStatusError:   "warning icon red",
+                       models.CommitStatusFailure: "remove icon red",
+                       models.CommitStatusWarning: "warning sign icon yellow",
+               }
+
+               // Update commit status, and check if icon is updated as well
+               for _, status := range statusList {
+
+                       // Call API to add status for commit
+                       token := getTokenForLoggedInUser(t, session)
+                       req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/user1/repo1/statuses/%s?token=%s", commitID, token),
+                               api.CreateStatusOption{
+                                       State:       api.StatusState(status),
+                                       TargetURL:   "http://test.ci/",
+                                       Description: "",
+                                       Context:     "testci",
+                               },
+                       )
+                       session.MakeRequest(t, req, http.StatusCreated)
+
+                       req = NewRequestf(t, "GET", "/user1/repo1/pulls/1/commits")
+                       resp = session.MakeRequest(t, req, http.StatusOK)
+                       doc = NewHTMLParser(t, resp.Body)
+
+                       commitURL, exists = doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
+                       assert.True(t, exists)
+                       assert.NotEmpty(t, commitURL)
+                       assert.EqualValues(t, commitID, path.Base(commitURL))
+
+                       cls, ok := doc.doc.Find("#commits-table tbody tr td.message i.commit-status").Last().Attr("class")
+                       assert.True(t, ok)
+                       assert.EqualValues(t, "commit-status "+statesIcons[status], cls)
+               }
+       })
 }
index fcdbda2c89302815ccacee4bd6554b1a47b4ad1f..cec5c79c4d200b974ecbc87a4646ff5823484df0 100644 (file)
@@ -6,6 +6,7 @@ package integrations
 
 import (
        "net/http"
+       "net/url"
        "strings"
        "testing"
 
@@ -16,49 +17,51 @@ import (
 )
 
 func TestRepoActivity(t *testing.T) {
-       prepareTestEnv(t)
-       session := loginUser(t, "user1")
-
-       // Create PRs (1 merged & 2 proposed)
-       testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
-       testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
-       resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
-       elem := strings.Split(test.RedirectURL(resp), "/")
-       assert.EqualValues(t, "pulls", elem[3])
-       testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
-
-       testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/better_readme", "README.md", "Hello, World (Edited Again)\n")
-       testPullCreate(t, session, "user1", "repo1", "feat/better_readme", "This is a pull title")
-
-       testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/much_better_readme", "README.md", "Hello, World (Edited More)\n")
-       testPullCreate(t, session, "user1", "repo1", "feat/much_better_readme", "This is a pull title")
-
-       // Create issues (3 new issues)
-       testNewIssue(t, session, "user2", "repo1", "Issue 1", "Description 1")
-       testNewIssue(t, session, "user2", "repo1", "Issue 2", "Description 2")
-       testNewIssue(t, session, "user2", "repo1", "Issue 3", "Description 3")
-
-       // Create releases (1 new release)
-       createNewRelease(t, session, "/user2/repo1", "v1.0.0", "v1.0.0", false, false)
-
-       // Open Activity page and check stats
-       req := NewRequest(t, "GET", "/user2/repo1/activity")
-       resp = session.MakeRequest(t, req, http.StatusOK)
-       htmlDoc := NewHTMLParser(t, resp.Body)
-
-       // Should be 1 published release
-       list := htmlDoc.doc.Find("#published-releases").Next().Find("p.desc")
-       assert.Len(t, list.Nodes, 1)
-
-       // Should be 1 merged pull request
-       list = htmlDoc.doc.Find("#merged-pull-requests").Next().Find("p.desc")
-       assert.Len(t, list.Nodes, 1)
-
-       // Should be 2 merged proposed pull requests
-       list = htmlDoc.doc.Find("#proposed-pull-requests").Next().Find("p.desc")
-       assert.Len(t, list.Nodes, 2)
-
-       // Should be 3 new issues
-       list = htmlDoc.doc.Find("#new-issues").Next().Find("p.desc")
-       assert.Len(t, list.Nodes, 3)
+       onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
+
+               session := loginUser(t, "user1")
+
+               // Create PRs (1 merged & 2 proposed)
+               testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+               testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
+               resp := testPullCreate(t, session, "user1", "repo1", "master", "This is a pull title")
+               elem := strings.Split(test.RedirectURL(resp), "/")
+               assert.EqualValues(t, "pulls", elem[3])
+               testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
+
+               testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/better_readme", "README.md", "Hello, World (Edited Again)\n")
+               testPullCreate(t, session, "user1", "repo1", "feat/better_readme", "This is a pull title")
+
+               testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/much_better_readme", "README.md", "Hello, World (Edited More)\n")
+               testPullCreate(t, session, "user1", "repo1", "feat/much_better_readme", "This is a pull title")
+
+               // Create issues (3 new issues)
+               testNewIssue(t, session, "user2", "repo1", "Issue 1", "Description 1")
+               testNewIssue(t, session, "user2", "repo1", "Issue 2", "Description 2")
+               testNewIssue(t, session, "user2", "repo1", "Issue 3", "Description 3")
+
+               // Create releases (1 new release)
+               createNewRelease(t, session, "/user2/repo1", "v1.0.0", "v1.0.0", false, false)
+
+               // Open Activity page and check stats
+               req := NewRequest(t, "GET", "/user2/repo1/activity")
+               resp = session.MakeRequest(t, req, http.StatusOK)
+               htmlDoc := NewHTMLParser(t, resp.Body)
+
+               // Should be 1 published release
+               list := htmlDoc.doc.Find("#published-releases").Next().Find("p.desc")
+               assert.Len(t, list.Nodes, 1)
+
+               // Should be 1 merged pull request
+               list = htmlDoc.doc.Find("#merged-pull-requests").Next().Find("p.desc")
+               assert.Len(t, list.Nodes, 1)
+
+               // Should be 2 merged proposed pull requests
+               list = htmlDoc.doc.Find("#proposed-pull-requests").Next().Find("p.desc")
+               assert.Len(t, list.Nodes, 2)
+
+               // Should be 3 new issues
+               list = htmlDoc.doc.Find("#new-issues").Next().Find("p.desc")
+               assert.Len(t, list.Nodes, 3)
+       })
 }
index 3101dc4c0febdd9eeed350978f1e0a4e1a40441f..a5447cfb665b5c9f60fe1567a426357520e18ee7 100644 (file)
@@ -6,6 +6,7 @@ package integrations
 
 import (
        "net/http"
+       "net/url"
        "path"
        "strings"
        "testing"
@@ -35,6 +36,10 @@ func testCreateBranch(t testing.TB, session *TestSession, user, repo, oldRefSubU
 }
 
 func TestCreateBranch(t *testing.T) {
+       onGiteaRun(t, testCreateBranches)
+}
+
+func testCreateBranches(t *testing.T, giteaURL *url.URL) {
        tests := []struct {
                OldRefSubURL   string
                NewBranch      string
diff --git a/integrations/repofiles_delete_test.go b/integrations/repofiles_delete_test.go
new file mode 100644 (file)
index 0000000..c3bb18e
--- /dev/null
@@ -0,0 +1,193 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package integrations
+
+import (
+       "net/url"
+       "testing"
+
+       "code.gitea.io/gitea/models"
+       "code.gitea.io/gitea/modules/repofiles"
+       api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/test"
+
+       "github.com/stretchr/testify/assert"
+)
+
+func getDeleteRepoFileOptions(repo *models.Repository) *repofiles.DeleteRepoFileOptions {
+       return &repofiles.DeleteRepoFileOptions{
+               LastCommitID: "",
+               OldBranch:    repo.DefaultBranch,
+               NewBranch:    repo.DefaultBranch,
+               TreePath:     "README.md",
+               Message:      "Deletes README.md",
+               SHA:          "4b4851ad51df6a7d9f25c979345979eaeb5b349f",
+               Author:       nil,
+               Committer:    nil,
+       }
+}
+
+func getExpectedDeleteFileResponse(u *url.URL) *api.FileResponse {
+       return &api.FileResponse{
+               Content: nil,
+               Commit: &api.FileCommitResponse{
+                       CommitMeta: api.CommitMeta{
+                               URL: u.String() + "api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d",
+                               SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
+                       },
+                       HTMLURL: u.String() + "user2/repo1/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d",
+                       Author: &api.CommitUser{
+                               Identity: api.Identity{
+                                       Name:  "user1",
+                                       Email: "address1@example.com",
+                               },
+                               Date: "2017-03-19T20:47:59Z",
+                       },
+                       Committer: &api.CommitUser{
+                               Identity: api.Identity{
+                                       Name:  "Ethan Koenig",
+                                       Email: "ethantkoenig@gmail.com",
+                               },
+                               Date: "2017-03-19T20:47:59Z",
+                       },
+                       Parents: []*api.CommitMeta{},
+                       Message: "Initial commit\n",
+                       Tree: &api.CommitMeta{
+                               URL: u.String() + "api/v1/repos/user2/repo1/git/trees/2a2f1d4670728a2e10049e345bd7a276468beab6",
+                               SHA: "2a2f1d4670728a2e10049e345bd7a276468beab6",
+                       },
+               },
+               Verification: &api.PayloadCommitVerification{
+                       Verified:  false,
+                       Reason:    "",
+                       Signature: "",
+                       Payload:   "",
+               },
+       }
+}
+
+func TestDeleteRepoFile(t *testing.T) {
+       onGiteaRun(t, testDeleteRepoFile)
+}
+
+func testDeleteRepoFile(t *testing.T, u *url.URL) {
+       // setup
+       models.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)
+       repo := ctx.Repo.Repository
+       doer := ctx.User
+       opts := getDeleteRepoFileOptions(repo)
+
+       t.Run("Delete README.md file", func(t *testing.T) {
+               fileResponse, err := repofiles.DeleteRepoFile(repo, doer, opts)
+               assert.Nil(t, err)
+               expectedFileResponse := getExpectedDeleteFileResponse(u)
+               assert.EqualValues(t, expectedFileResponse, fileResponse)
+       })
+
+       t.Run("Verify README.md has been deleted", func(t *testing.T) {
+               fileResponse, err := repofiles.DeleteRepoFile(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
+       models.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)
+       repo := ctx.Repo.Repository
+       doer := ctx.User
+       opts := getDeleteRepoFileOptions(repo)
+       opts.OldBranch = ""
+       opts.NewBranch = ""
+
+       t.Run("Delete README.md without Branch Name", func(t *testing.T) {
+               fileResponse, err := repofiles.DeleteRepoFile(repo, doer, opts)
+               assert.Nil(t, err)
+               expectedFileResponse := getExpectedDeleteFileResponse(u)
+               assert.EqualValues(t, expectedFileResponse, fileResponse)
+       })
+}
+
+func TestDeleteRepoFileErrors(t *testing.T) {
+       // setup
+       models.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)
+       repo := ctx.Repo.Repository
+       doer := ctx.User
+
+       t.Run("Bad branch", func(t *testing.T) {
+               opts := getDeleteRepoFileOptions(repo)
+               opts.OldBranch = "bad_branch"
+               fileResponse, err := repofiles.DeleteRepoFile(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 := repofiles.DeleteRepoFile(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 := repofiles.DeleteRepoFile(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 := repofiles.DeleteRepoFile(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 := repofiles.DeleteRepoFile(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)
+       })
+}
diff --git a/integrations/repofiles_update_test.go b/integrations/repofiles_update_test.go
new file mode 100644 (file)
index 0000000..02a9bbe
--- /dev/null
@@ -0,0 +1,365 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package integrations
+
+import (
+       "net/url"
+       "testing"
+       "time"
+
+       "code.gitea.io/gitea/models"
+       "code.gitea.io/gitea/modules/git"
+       "code.gitea.io/gitea/modules/repofiles"
+       "code.gitea.io/gitea/modules/setting"
+       api "code.gitea.io/gitea/modules/structs"
+       "code.gitea.io/gitea/modules/test"
+
+       "github.com/stretchr/testify/assert"
+)
+
+func getCreateRepoFileOptions(repo *models.Repository) *repofiles.UpdateRepoFileOptions {
+       return &repofiles.UpdateRepoFileOptions{
+               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 *models.Repository) *repofiles.UpdateRepoFileOptions {
+       return &repofiles.UpdateRepoFileOptions{
+               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 getExpectedFileResponseForRepofilesCreate(commitID string) *api.FileResponse {
+       return &api.FileResponse{
+               Content: &api.FileContentResponse{
+                       Name:        "file.txt",
+                       Path:        "new/file.txt",
+                       SHA:         "103ff9234cefeee5ec5361d22b49fbb04d385885",
+                       Size:        18,
+                       URL:         setting.AppURL + "api/v1/repos/user2/repo1/contents/new/file.txt",
+                       HTMLURL:     setting.AppURL + "user2/repo1/blob/master/new/file.txt",
+                       GitURL:      setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/103ff9234cefeee5ec5361d22b49fbb04d385885",
+                       DownloadURL: setting.AppURL + "user2/repo1/raw/branch/master/new/file.txt",
+                       Type:        "blob",
+                       Links: &api.FileLinksResponse{
+                               Self:    setting.AppURL + "api/v1/repos/user2/repo1/contents/new/file.txt",
+                               GitURL:  setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/103ff9234cefeee5ec5361d22b49fbb04d385885",
+                               HTMLURL: setting.AppURL + "user2/repo1/blob/master/new/file.txt",
+                       },
+               },
+               Commit: &api.FileCommitResponse{
+                       CommitMeta: api.CommitMeta{
+                               URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID,
+                               SHA: commitID,
+                       },
+                       HTMLURL: setting.AppURL + "user2/repo1/commit/" + commitID,
+                       Author: &api.CommitUser{
+                               Identity: api.Identity{
+                                       Name:  "User Two",
+                                       Email: "user2@noreply.example.org",
+                               },
+                               Date: time.Now().UTC().Format(time.RFC3339),
+                       },
+                       Committer: &api.CommitUser{
+                               Identity: api.Identity{
+                                       Name:  "User Two",
+                                       Email: "user2@noreply.example.org",
+                               },
+                               Date: time.Now().UTC().Format(time.RFC3339),
+                       },
+                       Parents: []*api.CommitMeta{
+                               {
+                                       URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d",
+                                       SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
+                               },
+                       },
+                       Message: "Updates README.md\n",
+                       Tree: &api.CommitMeta{
+                               URL: setting.AppURL + "api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc",
+                               SHA: "f93e3a1a1525fb5b91020git dda86e44810c87a2d7bc",
+                       },
+               },
+               Verification: &api.PayloadCommitVerification{
+                       Verified:  false,
+                       Reason:    "unsigned",
+                       Signature: "",
+                       Payload:   "",
+               },
+       }
+}
+
+func getExpectedFileResponseForRepofilesUpdate(commitID string) *api.FileResponse {
+       return &api.FileResponse{
+               Content: &api.FileContentResponse{
+                       Name:        "README.md",
+                       Path:        "README.md",
+                       SHA:         "dbf8d00e022e05b7e5cf7e535de857de57925647",
+                       Size:        43,
+                       URL:         setting.AppURL + "api/v1/repos/user2/repo1/contents/README.md",
+                       HTMLURL:     setting.AppURL + "user2/repo1/blob/master/README.md",
+                       GitURL:      setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/dbf8d00e022e05b7e5cf7e535de857de57925647",
+                       DownloadURL: setting.AppURL + "user2/repo1/raw/branch/master/README.md",
+                       Type:        "blob",
+                       Links: &api.FileLinksResponse{
+                               Self:    setting.AppURL + "api/v1/repos/user2/repo1/contents/README.md",
+                               GitURL:  setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/dbf8d00e022e05b7e5cf7e535de857de57925647",
+                               HTMLURL: setting.AppURL + "user2/repo1/blob/master/README.md",
+                       },
+               },
+               Commit: &api.FileCommitResponse{
+                       CommitMeta: api.CommitMeta{
+                               URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/" + commitID,
+                               SHA: commitID,
+                       },
+                       HTMLURL: setting.AppURL + "user2/repo1/commit/" + commitID,
+                       Author: &api.CommitUser{
+                               Identity: api.Identity{
+                                       Name:  "User Two",
+                                       Email: "user2@noreply.example.org",
+                               },
+                               Date: time.Now().UTC().Format(time.RFC3339),
+                       },
+                       Committer: &api.CommitUser{
+                               Identity: api.Identity{
+                                       Name:  "User Two",
+                                       Email: "user2@noreply.example.org",
+                               },
+                               Date: time.Now().UTC().Format(time.RFC3339),
+                       },
+                       Parents: []*api.CommitMeta{
+                               {
+                                       URL: setting.AppURL + "api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d",
+                                       SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
+                               },
+                       },
+                       Message: "Updates README.md\n",
+                       Tree: &api.CommitMeta{
+                               URL: setting.AppURL + "api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc",
+                               SHA: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc",
+                       },
+               },
+               Verification: &api.PayloadCommitVerification{
+                       Verified:  false,
+                       Reason:    "unsigned",
+                       Signature: "",
+                       Payload:   "",
+               },
+       }
+}
+
+func TestCreateOrUpdateRepoFileForCreate(t *testing.T) {
+       // setup
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               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)
+               repo := ctx.Repo.Repository
+               doer := ctx.User
+               opts := getCreateRepoFileOptions(repo)
+
+               // test
+               fileResponse, err := repofiles.CreateOrUpdateRepoFile(repo, doer, opts)
+
+               // asserts
+               assert.Nil(t, err)
+               gitRepo, _ := git.OpenRepository(repo.RepoPath())
+               commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
+               expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID)
+               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)
+       })
+}
+
+func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) {
+       // setup
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               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)
+               repo := ctx.Repo.Repository
+               doer := ctx.User
+               opts := getUpdateRepoFileOptions(repo)
+
+               // test
+               fileResponse, err := repofiles.CreateOrUpdateRepoFile(repo, doer, opts)
+
+               // asserts
+               assert.Nil(t, err)
+               gitRepo, _ := git.OpenRepository(repo.RepoPath())
+               commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
+               expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID)
+               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)
+       })
+}
+
+func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) {
+       // setup
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               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)
+               repo := ctx.Repo.Repository
+               doer := ctx.User
+               opts := getUpdateRepoFileOptions(repo)
+               suffix := "_new"
+               opts.FromTreePath = "README.md"
+               opts.TreePath = "README.md" + suffix // new file name, README.md_new
+
+               // test
+               fileResponse, err := repofiles.CreateOrUpdateRepoFile(repo, doer, opts)
+
+               // asserts
+               assert.Nil(t, err)
+               gitRepo, _ := git.OpenRepository(repo.RepoPath())
+               commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
+               expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String())
+               // assert that the old file no longer exists in the last commit of the branch
+               fromEntry, err := commit.GetTreeEntryByPath(opts.FromTreePath)
+               toEntry, err := commit.GetTreeEntryByPath(opts.TreePath)
+               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+suffix, fileResponse.Content.Name)
+               assert.EqualValues(t, expectedFileResponse.Content.Path+suffix, fileResponse.Content.Path)
+               assert.EqualValues(t, expectedFileResponse.Content.URL+suffix, fileResponse.Content.URL)
+               assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
+               assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
+       })
+}
+
+// Test opts with branch names removed, should get same results as above test
+func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) {
+       // setup
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               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)
+               repo := ctx.Repo.Repository
+               doer := ctx.User
+               opts := getUpdateRepoFileOptions(repo)
+               opts.OldBranch = ""
+               opts.NewBranch = ""
+
+               // test
+               fileResponse, err := repofiles.CreateOrUpdateRepoFile(repo, doer, opts)
+
+               // asserts
+               assert.Nil(t, err)
+               gitRepo, _ := git.OpenRepository(repo.RepoPath())
+               commitID, _ := gitRepo.GetBranchCommitID(repo.DefaultBranch)
+               expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID)
+               assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
+       })
+}
+
+func TestCreateOrUpdateRepoFileErrors(t *testing.T) {
+       // setup
+       onGiteaRun(t, func(t *testing.T, u *url.URL) {
+               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)
+               repo := ctx.Repo.Repository
+               doer := ctx.User
+
+               t.Run("bad branch", func(t *testing.T) {
+                       opts := getUpdateRepoFileOptions(repo)
+                       opts.OldBranch = "bad_branch"
+                       fileResponse, err := repofiles.CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
+                       origSHA := opts.SHA
+                       opts.SHA = "bad_sha"
+                       fileResponse, err := repofiles.CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
+                       opts.NewBranch = "develop"
+                       fileResponse, err := repofiles.CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
+                       opts.TreePath = ""
+                       fileResponse, err := repofiles.CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
+                       opts.TreePath = ".git"
+                       fileResponse, err := repofiles.CreateOrUpdateRepoFile(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)
+               })
+
+               t.Run("create file that already exists", func(t *testing.T) {
+                       opts := getCreateRepoFileOptions(repo)
+                       opts.TreePath = "README.md" //already exists
+                       fileResponse, err := repofiles.CreateOrUpdateRepoFile(repo, doer, opts)
+                       assert.Nil(t, fileResponse)
+                       assert.Error(t, err)
+                       expectedError := "repository file already exists [path: " + opts.TreePath + "]"
+                       assert.EqualError(t, err, expectedError)
+               })
+       })
+}
diff --git a/models/helper_directory.go b/models/helper_directory.go
new file mode 100644 (file)
index 0000000..417402b
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package models
+
+import (
+       "fmt"
+       "os"
+       "path"
+       "path/filepath"
+       "time"
+
+       "code.gitea.io/gitea/modules/log"
+       "code.gitea.io/gitea/modules/setting"
+
+       "github.com/Unknwon/com"
+)
+
+// LocalCopyPath returns the local repository temporary copy path.
+func LocalCopyPath() string {
+       if filepath.IsAbs(setting.Repository.Local.LocalCopyPath) {
+               return setting.Repository.Local.LocalCopyPath
+       }
+       return path.Join(setting.AppDataPath, setting.Repository.Local.LocalCopyPath)
+}
+
+// CreateTemporaryPath creates a temporary path
+func CreateTemporaryPath(prefix string) (string, error) {
+       timeStr := com.ToStr(time.Now().Nanosecond()) // SHOULD USE SOMETHING UNIQUE
+       basePath := path.Join(LocalCopyPath(), prefix+"-"+timeStr+".git")
+       if err := os.MkdirAll(filepath.Dir(basePath), os.ModePerm); err != nil {
+               log.Error("Unable to create temporary directory: %s (%v)", basePath, err)
+               return "", fmt.Errorf("Failed to create dir %s: %v", basePath, err)
+       }
+       return basePath, nil
+}
+
+// RemoveTemporaryPath removes the temporary path
+func RemoveTemporaryPath(basePath string) error {
+       if _, err := os.Stat(basePath); !os.IsNotExist(err) {
+               return os.RemoveAll(basePath)
+       }
+       return nil
+}
diff --git a/models/helper_environment.go b/models/helper_environment.go
new file mode 100644 (file)
index 0000000..283584c
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package models
+
+import (
+       "fmt"
+       "os"
+       "strings"
+)
+
+// PushingEnvironment returns an os environment to allow hooks to work on push
+func PushingEnvironment(doer *User, repo *Repository) []string {
+       isWiki := "false"
+       if strings.HasSuffix(repo.Name, ".wiki") {
+               isWiki = "true"
+       }
+
+       sig := doer.NewGitSig()
+
+       return append(os.Environ(),
+               "GIT_AUTHOR_NAME="+sig.Name,
+               "GIT_AUTHOR_EMAIL="+sig.Email,
+               "GIT_COMMITTER_NAME="+sig.Name,
+               "GIT_COMMITTER_EMAIL="+sig.Email,
+               EnvRepoName+"="+repo.Name,
+               EnvRepoUsername+"="+repo.OwnerName,
+               EnvRepoIsWiki+"="+isWiki,
+               EnvPusherName+"="+doer.Name,
+               EnvPusherID+"="+fmt.Sprintf("%d", doer.ID),
+               ProtectedBranchRepoID+"="+fmt.Sprintf("%d", repo.ID),
+               "SSH_ORIGINAL_COMMAND=gitea-internal",
+       )
+
+}
index 7382cbd126a6b37f2d1897f5bbc1fa92036c0961..6f37145d9bebf20d78ca66ed0cf7836bb78f69c5 100644 (file)
@@ -418,22 +418,21 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
                go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false)
        }()
 
-       headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
-
        // Clone base repo.
-       tmpBasePath := path.Join(LocalCopyPath(), "merge-"+com.ToStr(time.Now().Nanosecond())+".git")
-
-       if err := os.MkdirAll(path.Dir(tmpBasePath), os.ModePerm); err != nil {
-               return fmt.Errorf("Failed to create dir %s: %v", tmpBasePath, err)
+       tmpBasePath, err := CreateTemporaryPath("merge")
+       if err != nil {
+               return err
        }
+       defer RemoveTemporaryPath(tmpBasePath)
 
-       defer os.RemoveAll(tmpBasePath)
+       headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
 
-       var stderr string
-       if _, stderr, err = process.GetManager().ExecTimeout(5*time.Minute,
-               fmt.Sprintf("PullRequest.Merge (git clone): %s", tmpBasePath),
-               "git", "clone", "-s", "--no-checkout", "-b", pr.BaseBranch, baseGitRepo.Path, tmpBasePath); err != nil {
-               return fmt.Errorf("git clone: %s", stderr)
+       if err := git.Clone(baseGitRepo.Path, tmpBasePath, git.CloneRepoOptions{
+               Shared:     true,
+               NoCheckout: true,
+               Branch:     pr.BaseBranch,
+       }); err != nil {
+               return fmt.Errorf("git clone: %v", err)
        }
 
        remoteRepoName := "head_repo"
@@ -456,14 +455,14 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
        if err := addCacheRepo(tmpBasePath, headRepoPath); err != nil {
                return fmt.Errorf("addCacheRepo [%s -> %s]: %v", headRepoPath, tmpBasePath, err)
        }
-       if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+       if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                fmt.Sprintf("PullRequest.Merge (git remote add): %s", tmpBasePath),
                "git", "remote", "add", remoteRepoName, headRepoPath); err != nil {
                return fmt.Errorf("git remote add [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
        }
 
        // Fetch head branch
-       if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+       if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                fmt.Sprintf("PullRequest.Merge (git fetch): %s", tmpBasePath),
                "git", "fetch", remoteRepoName); err != nil {
                return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
@@ -487,14 +486,14 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
                return fmt.Errorf("Writing sparse-checkout file to %s: %v", sparseCheckoutListPath, err)
        }
 
-       if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+       if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                fmt.Sprintf("PullRequest.Merge (git config): %s", tmpBasePath),
                "git", "config", "--local", "core.sparseCheckout", "true"); err != nil {
                return fmt.Errorf("git config [core.sparsecheckout -> true]: %v", stderr)
        }
 
        // Read base branch index
-       if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+       if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                fmt.Sprintf("PullRequest.Merge (git read-tree): %s", tmpBasePath),
                "git", "read-tree", "HEAD"); err != nil {
                return fmt.Errorf("git read-tree HEAD: %s", stderr)
@@ -503,14 +502,14 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
        // Merge commits.
        switch mergeStyle {
        case MergeStyleMerge:
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git merge --no-ff --no-commit): %s", tmpBasePath),
                        "git", "merge", "--no-ff", "--no-commit", trackingBranch); err != nil {
                        return fmt.Errorf("git merge --no-ff --no-commit [%s]: %v - %s", tmpBasePath, err, stderr)
                }
 
                sig := doer.NewGitSig()
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git merge): %s", tmpBasePath),
                        "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
                        "-m", message); err != nil {
@@ -518,50 +517,50 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
                }
        case MergeStyleRebase:
                // Checkout head branch
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath),
                        "git", "checkout", "-b", stagingBranch, trackingBranch); err != nil {
                        return fmt.Errorf("git checkout: %s", stderr)
                }
                // Rebase before merging
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git rebase): %s", tmpBasePath),
                        "git", "rebase", "-q", pr.BaseBranch); err != nil {
                        return fmt.Errorf("git rebase [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
                }
                // Checkout base branch again
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath),
                        "git", "checkout", pr.BaseBranch); err != nil {
                        return fmt.Errorf("git checkout: %s", stderr)
                }
                // Merge fast forward
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git rebase): %s", tmpBasePath),
                        "git", "merge", "--ff-only", "-q", stagingBranch); err != nil {
                        return fmt.Errorf("git merge --ff-only [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
                }
        case MergeStyleRebaseMerge:
                // Checkout head branch
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath),
                        "git", "checkout", "-b", stagingBranch, trackingBranch); err != nil {
                        return fmt.Errorf("git checkout: %s", stderr)
                }
                // Rebase before merging
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git rebase): %s", tmpBasePath),
                        "git", "rebase", "-q", pr.BaseBranch); err != nil {
                        return fmt.Errorf("git rebase [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
                }
                // Checkout base branch again
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath),
                        "git", "checkout", pr.BaseBranch); err != nil {
                        return fmt.Errorf("git checkout: %s", stderr)
                }
                // Prepare merge with commit
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git merge): %s", tmpBasePath),
                        "git", "merge", "--no-ff", "--no-commit", "-q", stagingBranch); err != nil {
                        return fmt.Errorf("git merge --no-ff [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
@@ -569,7 +568,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
 
                // Set custom message and author and create merge commit
                sig := doer.NewGitSig()
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git commit): %s", tmpBasePath),
                        "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
                        "-m", message); err != nil {
@@ -578,13 +577,13 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
 
        case MergeStyleSquash:
                // Merge with squash
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git squash): %s", tmpBasePath),
                        "git", "merge", "-q", "--squash", trackingBranch); err != nil {
                        return fmt.Errorf("git merge --squash [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
                }
                sig := pr.Issue.Poster.NewGitSig()
-               if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+               if _, stderr, err := process.GetManager().ExecDir(-1, tmpBasePath,
                        fmt.Sprintf("PullRequest.Merge (git squash): %s", tmpBasePath),
                        "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
                        "-m", message); err != nil {
@@ -594,10 +593,12 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
                return ErrInvalidMergeStyle{pr.BaseRepo.ID, mergeStyle}
        }
 
+       env := PushingEnvironment(doer, pr.BaseRepo)
+
        // Push back to upstream.
-       if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
+       if _, stderr, err := process.GetManager().ExecDirEnv(-1, tmpBasePath,
                fmt.Sprintf("PullRequest.Merge (git push): %s", tmpBasePath),
-               "git", "push", baseGitRepo.Path, pr.BaseBranch); err != nil {
+               env, "git", "push", baseGitRepo.Path, pr.BaseBranch); err != nil {
                return fmt.Errorf("git push: %s", stderr)
        }
 
index 66c1bdbab1981d6871aec1d8686967da86966296..2f87e2f514e2cb9c0ad3be4f6fc0cf4f50b3327d 100644 (file)
@@ -518,7 +518,7 @@ func (repo *Repository) DeleteWiki() error {
 }
 
 func (repo *Repository) deleteWiki(e Engine) error {
-       wikiPaths := []string{repo.WikiPath(), repo.LocalWikiPath()}
+       wikiPaths := []string{repo.WikiPath()}
        for _, wikiPath := range wikiPaths {
                removeAllWithNotice(e, "Delete repository wiki", wikiPath)
        }
@@ -749,56 +749,6 @@ func (repo *Repository) DescriptionHTML() template.HTML {
        return template.HTML(markup.Sanitize(string(desc)))
 }
 
-// LocalCopyPath returns the local repository copy path.
-func LocalCopyPath() string {
-       if filepath.IsAbs(setting.Repository.Local.LocalCopyPath) {
-               return setting.Repository.Local.LocalCopyPath
-       }
-       return path.Join(setting.AppDataPath, setting.Repository.Local.LocalCopyPath)
-}
-
-// LocalCopyPath returns the local repository copy path for the given repo.
-func (repo *Repository) LocalCopyPath() string {
-       return path.Join(LocalCopyPath(), com.ToStr(repo.ID))
-}
-
-// UpdateLocalCopyBranch pulls latest changes of given branch from repoPath to localPath.
-// It creates a new clone if local copy does not exist.
-// This function checks out target branch by default, it is safe to assume subsequent
-// operations are operating against target branch when caller has confidence for no race condition.
-func UpdateLocalCopyBranch(repoPath, localPath, branch string) error {
-       if !com.IsExist(localPath) {
-               if err := git.Clone(repoPath, localPath, git.CloneRepoOptions{
-                       Timeout: time.Duration(setting.Git.Timeout.Clone) * time.Second,
-                       Branch:  branch,
-               }); err != nil {
-                       return fmt.Errorf("git clone %s: %v", branch, err)
-               }
-       } else {
-               _, err := git.NewCommand("fetch", "origin").RunInDir(localPath)
-               if err != nil {
-                       return fmt.Errorf("git fetch origin: %v", err)
-               }
-               if len(branch) > 0 {
-                       if err := git.Checkout(localPath, git.CheckoutOptions{
-                               Branch: branch,
-                       }); err != nil {
-                               return fmt.Errorf("git checkout %s: %v", branch, err)
-                       }
-
-                       if err := git.ResetHEAD(localPath, true, "origin/"+branch); err != nil {
-                               return fmt.Errorf("git reset --hard origin/%s: %v", branch, err)
-                       }
-               }
-       }
-       return nil
-}
-
-// UpdateLocalCopyBranch makes sure local copy of repository in given branch is up-to-date.
-func (repo *Repository) UpdateLocalCopyBranch(branch string) error {
-       return UpdateLocalCopyBranch(repo.RepoPath(), repo.LocalCopyPath(), branch)
-}
-
 // PatchPath returns corresponding patch file path of repository by given issue ID.
 func (repo *Repository) PatchPath(index int64) (string, error) {
        return repo.patchPath(x, index)
@@ -1583,12 +1533,10 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
        if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
                return fmt.Errorf("rename repository directory: %v", err)
        }
-       removeAllWithNotice(sess, "Delete repository local copy", repo.LocalCopyPath())
 
        // Rename remote wiki repository to new path and delete local copy.
        wikiPath := WikiPath(owner.Name, repo.Name)
        if com.IsExist(wikiPath) {
-               removeAllWithNotice(sess, "Delete repository wiki local copy", repo.LocalWikiPath())
                if err = os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil {
                        return fmt.Errorf("rename repository wiki: %v", err)
                }
@@ -1633,20 +1581,11 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
                return fmt.Errorf("rename repository directory: %v", err)
        }
 
-       localPath := repo.LocalCopyPath()
-       if com.IsExist(localPath) {
-               _, err := git.NewCommand("remote", "set-url", "origin", newRepoPath).RunInDir(localPath)
-               if err != nil {
-                       return fmt.Errorf("git remote set-url origin %s: %v", newRepoPath, err)
-               }
-       }
-
        wikiPath := repo.WikiPath()
        if com.IsExist(wikiPath) {
                if err = os.Rename(wikiPath, WikiPath(u.Name, newRepoName)); err != nil {
                        return fmt.Errorf("rename repository wiki: %v", err)
                }
-               RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
        }
 
        sess := x.NewSession()
index 0958e239745318d3d413c5b6bfc24127b7733164..08c881fc24c29d378433f38011693787938d659d 100644 (file)
@@ -7,86 +7,11 @@ package models
 
 import (
        "fmt"
-       "time"
 
        "code.gitea.io/gitea/modules/git"
-       "code.gitea.io/gitea/modules/setting"
-
-       "github.com/Unknwon/com"
+       "code.gitea.io/gitea/modules/log"
 )
 
-// discardLocalRepoBranchChanges discards local commits/changes of
-// given branch to make sure it is even to remote branch.
-func discardLocalRepoBranchChanges(localPath, branch string) error {
-       if !com.IsExist(localPath) {
-               return nil
-       }
-       // No need to check if nothing in the repository.
-       if !git.IsBranchExist(localPath, branch) {
-               return nil
-       }
-
-       refName := "origin/" + branch
-       if err := git.ResetHEAD(localPath, true, refName); err != nil {
-               return fmt.Errorf("git reset --hard %s: %v", refName, err)
-       }
-       return nil
-}
-
-// DiscardLocalRepoBranchChanges discards the local repository branch changes
-func (repo *Repository) DiscardLocalRepoBranchChanges(branch string) error {
-       return discardLocalRepoBranchChanges(repo.LocalCopyPath(), branch)
-}
-
-// checkoutNewBranch checks out to a new branch from the a branch name.
-func checkoutNewBranch(repoPath, localPath, oldBranch, newBranch string) error {
-       if err := git.Checkout(localPath, git.CheckoutOptions{
-               Timeout:   time.Duration(setting.Git.Timeout.Pull) * time.Second,
-               Branch:    newBranch,
-               OldBranch: oldBranch,
-       }); err != nil {
-               return fmt.Errorf("git checkout -b %s %s: %v", newBranch, oldBranch, err)
-       }
-       return nil
-}
-
-// CheckoutNewBranch checks out a new branch
-func (repo *Repository) CheckoutNewBranch(oldBranch, newBranch string) error {
-       return checkoutNewBranch(repo.RepoPath(), repo.LocalCopyPath(), oldBranch, newBranch)
-}
-
-// deleteLocalBranch deletes a branch from a local repo cache
-// First checks out default branch to avoid trying to delete the currently checked out branch
-func deleteLocalBranch(localPath, defaultBranch, deleteBranch string) error {
-       if !com.IsExist(localPath) {
-               return nil
-       }
-
-       if !git.IsBranchExist(localPath, deleteBranch) {
-               return nil
-       }
-
-       // Must NOT have branch currently checked out
-       // Checkout default branch first
-       if err := git.Checkout(localPath, git.CheckoutOptions{
-               Timeout: time.Duration(setting.Git.Timeout.Pull) * time.Second,
-               Branch:  defaultBranch,
-       }); err != nil {
-               return fmt.Errorf("git checkout %s: %v", defaultBranch, err)
-       }
-
-       cmd := git.NewCommand("branch")
-       cmd.AddArguments("-D")
-       cmd.AddArguments(deleteBranch)
-       _, err := cmd.RunInDir(localPath)
-       return err
-}
-
-// DeleteLocalBranch deletes a branch from the local repo
-func (repo *Repository) DeleteLocalBranch(branchName string) error {
-       return deleteLocalBranch(repo.LocalCopyPath(), repo.DefaultBranch, branchName)
-}
-
 // CanCreateBranch returns true if repository meets the requirements for creating new branches.
 func (repo *Repository) CanCreateBranch() bool {
        return !repo.IsMirror
@@ -137,92 +62,86 @@ func (repo *Repository) CheckBranchName(name string) error {
 
 // CreateNewBranch creates a new repository branch
 func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName string) (err error) {
-       repoWorkingPool.CheckIn(com.ToStr(repo.ID))
-       defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
-
        // Check if branch name can be used
        if err := repo.CheckBranchName(branchName); err != nil {
                return err
        }
 
-       localPath := repo.LocalCopyPath()
-
-       if err = discardLocalRepoBranchChanges(localPath, oldBranchName); err != nil {
-               return fmt.Errorf("discardLocalRepoChanges: %v", err)
-       } else if err = repo.UpdateLocalCopyBranch(oldBranchName); err != nil {
-               return fmt.Errorf("UpdateLocalCopyBranch: %v", err)
+       if !git.IsBranchExist(repo.RepoPath(), oldBranchName) {
+               return fmt.Errorf("OldBranch: %s does not exist. Cannot create new branch from this", oldBranchName)
        }
 
-       if err = repo.CheckoutNewBranch(oldBranchName, branchName); err != nil {
-               return fmt.Errorf("CreateNewBranch: %v", err)
+       basePath, err := CreateTemporaryPath("branch-maker")
+       if err != nil {
+               return err
        }
+       defer RemoveTemporaryPath(basePath)
 
-       if err = git.Push(localPath, git.PushOptions{
-               Remote: "origin",
-               Branch: branchName,
+       if err := git.Clone(repo.RepoPath(), basePath, git.CloneRepoOptions{
+               Bare:   true,
+               Shared: true,
        }); err != nil {
-               return fmt.Errorf("Push: %v", err)
+               log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
+               return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err)
        }
 
-       return nil
-}
+       gitRepo, err := git.OpenRepository(basePath)
+       if err != nil {
+               log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
+               return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
+       }
 
-// updateLocalCopyToCommit pulls latest changes of given commit from repoPath to localPath.
-// It creates a new clone if local copy does not exist.
-// This function checks out target commit by default, it is safe to assume subsequent
-// operations are operating against target commit when caller has confidence for no race condition.
-func updateLocalCopyToCommit(repoPath, localPath, commit string) error {
-       if !com.IsExist(localPath) {
-               if err := git.Clone(repoPath, localPath, git.CloneRepoOptions{
-                       Timeout: time.Duration(setting.Git.Timeout.Clone) * time.Second,
-               }); err != nil {
-                       return fmt.Errorf("git clone: %v", err)
-               }
-       } else {
-               _, err := git.NewCommand("fetch", "origin").RunInDir(localPath)
-               if err != nil {
-                       return fmt.Errorf("git fetch origin: %v", err)
-               }
-               if err := git.ResetHEAD(localPath, true, "HEAD"); err != nil {
-                       return fmt.Errorf("git reset --hard HEAD: %v", err)
-               }
+       if err = gitRepo.CreateBranch(branchName, oldBranchName); err != nil {
+               log.Error("Unable to create branch: %s from %s. (%v)", branchName, oldBranchName, err)
+               return fmt.Errorf("Unable to create branch: %s from %s. (%v)", branchName, oldBranchName, err)
        }
-       if err := git.Checkout(localPath, git.CheckoutOptions{
-               Branch: commit,
+
+       if err = git.Push(basePath, git.PushOptions{
+               Remote: "origin",
+               Branch: branchName,
+               Env:    PushingEnvironment(doer, repo),
        }); err != nil {
-               return fmt.Errorf("git checkout %s: %v", commit, err)
+               return fmt.Errorf("Push: %v", err)
        }
-       return nil
-}
 
-// updateLocalCopyToCommit makes sure local copy of repository is at given commit.
-func (repo *Repository) updateLocalCopyToCommit(commit string) error {
-       return updateLocalCopyToCommit(repo.RepoPath(), repo.LocalCopyPath(), commit)
+       return nil
 }
 
 // CreateNewBranchFromCommit creates a new repository branch
 func (repo *Repository) CreateNewBranchFromCommit(doer *User, commit, branchName string) (err error) {
-       repoWorkingPool.CheckIn(com.ToStr(repo.ID))
-       defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
-
        // Check if branch name can be used
        if err := repo.CheckBranchName(branchName); err != nil {
                return err
        }
+       basePath, err := CreateTemporaryPath("branch-maker")
+       if err != nil {
+               return err
+       }
+       defer RemoveTemporaryPath(basePath)
 
-       localPath := repo.LocalCopyPath()
+       if err := git.Clone(repo.RepoPath(), basePath, git.CloneRepoOptions{
+               Bare:   true,
+               Shared: true,
+       }); err != nil {
+               log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
+               return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err)
+       }
 
-       if err = repo.updateLocalCopyToCommit(commit); err != nil {
-               return fmt.Errorf("UpdateLocalCopyBranch: %v", err)
+       gitRepo, err := git.OpenRepository(basePath)
+       if err != nil {
+               log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
+               return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
        }
 
-       if err = repo.CheckoutNewBranch(commit, branchName); err != nil {
-               return fmt.Errorf("CheckoutNewBranch: %v", err)
+       if err = gitRepo.CreateBranch(branchName, commit); err != nil {
+               log.Error("Unable to create branch: %s from %s. (%v)", branchName, commit, err)
+               return fmt.Errorf("Unable to create branch: %s from %s. (%v)", branchName, commit, err)
        }
 
-       if err = git.Push(localPath, git.PushOptions{
+       if err = git.Push(basePath, git.PushOptions{
                Remote: "origin",
                Branch: branchName,
+               Env:    PushingEnvironment(doer, repo),
        }); err != nil {
                return fmt.Errorf("Push: %v", err)
        }
index a5b8cce9b993a01e88c9d5eb0ce80ae3d043df15..eee39978680221174eec96f81c91dbd609a086c4 100644 (file)
@@ -5,11 +5,9 @@
 package models
 
 import (
-       "path"
        "testing"
 
        "code.gitea.io/gitea/modules/markup"
-       "code.gitea.io/gitea/modules/setting"
 
        "github.com/Unknwon/com"
        "github.com/stretchr/testify/assert"
@@ -138,25 +136,6 @@ func TestRepoAPIURL(t *testing.T) {
        assert.Equal(t, "https://try.gitea.io/api/v1/repos/user12/repo10", repo.APIURL())
 }
 
-func TestRepoLocalCopyPath(t *testing.T) {
-       assert.NoError(t, PrepareTestDatabase())
-
-       repo, err := GetRepositoryByID(10)
-       assert.NoError(t, err)
-       assert.NotNil(t, repo)
-
-       // test default
-       repoID := com.ToStr(repo.ID)
-       expected := path.Join(setting.AppDataPath, setting.Repository.Local.LocalCopyPath, repoID)
-       assert.Equal(t, expected, repo.LocalCopyPath())
-
-       // test absolute setting
-       tempPath := "/tmp/gitea/local-copy-path"
-       expected = path.Join(tempPath, repoID)
-       setting.Repository.Local.LocalCopyPath = tempPath
-       assert.Equal(t, expected, repo.LocalCopyPath())
-}
-
 func TestTransferOwnership(t *testing.T) {
        assert.NoError(t, PrepareTestDatabase())
 
index 0c445b5afd45108b3e8f53d3c763766cea683da9..90ca189ef0e028eaae0f11ae93729050ca22e23e 100644 (file)
@@ -943,17 +943,6 @@ func ChangeUserName(u *User, newUserName string) (err error) {
                return fmt.Errorf("ChangeUsernameInPullRequests: %v", err)
        }
 
-       // Delete all local copies of repository wiki that user owns.
-       if err = x.BufferSize(setting.IterateBufferSize).
-               Where("owner_id=?", u.ID).
-               Iterate(new(Repository), func(idx int, bean interface{}) error {
-                       repo := bean.(*Repository)
-                       RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
-                       return nil
-               }); err != nil {
-               return fmt.Errorf("Delete repository wiki local copy: %v", err)
-       }
-
        // Do not fail if directory does not exist
        if err = os.Rename(UserPath(u.Name), UserPath(newUserName)); err != nil && !os.IsNotExist(err) {
                return fmt.Errorf("Rename user directory: %v", err)
index 0f5cdc20bd1f4f30db2e149c5c7e8c7ffca2db57..bcf97c076573b14f480cbae01a2642aef63a6a3a 100644 (file)
@@ -6,15 +6,13 @@ package models
 
 import (
        "fmt"
-       "io/ioutil"
        "net/url"
        "os"
-       "path"
        "path/filepath"
        "strings"
 
        "code.gitea.io/gitea/modules/git"
-       "code.gitea.io/gitea/modules/setting"
+       "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/sync"
 
        "github.com/Unknwon/com"
@@ -89,34 +87,6 @@ func (repo *Repository) InitWiki() error {
        return nil
 }
 
-// LocalWikiPath returns the local wiki repository copy path.
-func LocalWikiPath() string {
-       if filepath.IsAbs(setting.Repository.Local.LocalWikiPath) {
-               return setting.Repository.Local.LocalWikiPath
-       }
-       return path.Join(setting.AppDataPath, setting.Repository.Local.LocalWikiPath)
-}
-
-// LocalWikiPath returns the path to the local wiki repository (?).
-func (repo *Repository) LocalWikiPath() string {
-       return path.Join(LocalWikiPath(), com.ToStr(repo.ID))
-}
-
-// UpdateLocalWiki makes sure the local copy of repository wiki is up-to-date.
-func (repo *Repository) updateLocalWiki() error {
-       // Don't pass branch name here because it fails to clone and
-       // checkout to a specific branch when wiki is an empty repository.
-       var branch = ""
-       if com.IsExist(repo.LocalWikiPath()) {
-               branch = "master"
-       }
-       return UpdateLocalCopyBranch(repo.WikiPath(), repo.LocalWikiPath(), branch)
-}
-
-func discardLocalWikiChanges(localPath string) error {
-       return discardLocalRepoBranchChanges(localPath, "master")
-}
-
 // nameAllowed checks if a wiki name is allowed
 func nameAllowed(name string) error {
        for _, reservedName := range reservedWikiNames {
@@ -132,7 +102,6 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con
        if err = nameAllowed(newWikiName); err != nil {
                return err
        }
-
        wikiWorkingPool.CheckIn(com.ToStr(repo.ID))
        defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID))
 
@@ -140,54 +109,113 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con
                return fmt.Errorf("InitWiki: %v", err)
        }
 
-       localPath := repo.LocalWikiPath()
-       if err = discardLocalWikiChanges(localPath); err != nil {
-               return fmt.Errorf("discardLocalWikiChanges: %v", err)
-       } else if err = repo.updateLocalWiki(); err != nil {
-               return fmt.Errorf("UpdateLocalWiki: %v", err)
+       hasMasterBranch := git.IsBranchExist(repo.WikiPath(), "master")
+
+       basePath, err := CreateTemporaryPath("update-wiki")
+       if err != nil {
+               return err
        }
+       defer RemoveTemporaryPath(basePath)
 
-       newWikiPath := path.Join(localPath, WikiNameToFilename(newWikiName))
+       cloneOpts := git.CloneRepoOptions{
+               Bare:   true,
+               Shared: true,
+       }
+
+       if hasMasterBranch {
+               cloneOpts.Branch = "master"
+       }
 
-       // If not a new file, show perform update not create.
+       if err := git.Clone(repo.WikiPath(), basePath, cloneOpts); err != nil {
+               log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
+               return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err)
+       }
+
+       gitRepo, err := git.OpenRepository(basePath)
+       if err != nil {
+               log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
+               return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
+       }
+
+       if hasMasterBranch {
+               if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
+                       log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
+                       return fmt.Errorf("Unable to read HEAD tree to index in: %s %v", basePath, err)
+               }
+       }
+
+       newWikiPath := WikiNameToFilename(newWikiName)
        if isNew {
-               if com.IsExist(newWikiPath) {
-                       return ErrWikiAlreadyExist{newWikiPath}
+               filesInIndex, err := gitRepo.LsFiles(newWikiPath)
+               if err != nil {
+                       log.Error("%v", err)
+                       return err
+               }
+               for _, file := range filesInIndex {
+                       if file == newWikiPath {
+                               return ErrWikiAlreadyExist{newWikiPath}
+                       }
                }
        } else {
-               oldWikiPath := path.Join(localPath, WikiNameToFilename(oldWikiName))
-               if err := os.Remove(oldWikiPath); err != nil {
-                       return fmt.Errorf("Failed to remove %s: %v", oldWikiPath, err)
+               oldWikiPath := WikiNameToFilename(oldWikiName)
+               filesInIndex, err := gitRepo.LsFiles(oldWikiPath)
+               if err != nil {
+                       log.Error("%v", err)
+                       return err
+               }
+               found := false
+               for _, file := range filesInIndex {
+                       if file == oldWikiPath {
+                               found = true
+                               break
+                       }
+               }
+               if found {
+                       err := gitRepo.RemoveFilesFromIndex(oldWikiPath)
+                       if err != nil {
+                               log.Error("%v", err)
+                               return err
+                       }
                }
        }
 
-       // SECURITY: if new file is a symlink to non-exist critical file,
-       // attack content can be written to the target file (e.g. authorized_keys2)
-       // as a new page operation.
-       // So we want to make sure the symlink is removed before write anything.
-       // The new file we created will be in normal text format.
-       if err = os.RemoveAll(newWikiPath); err != nil {
+       // FIXME: The wiki doesn't have lfs support at present - if this changes need to check attributes here
+
+       objectHash, err := gitRepo.HashObject(strings.NewReader(content))
+       if err != nil {
+               log.Error("%v", err)
                return err
        }
 
-       if err = ioutil.WriteFile(newWikiPath, []byte(content), 0666); err != nil {
-               return fmt.Errorf("WriteFile: %v", err)
+       if err := gitRepo.AddObjectToIndex("100644", objectHash, newWikiPath); err != nil {
+               log.Error("%v", err)
+               return err
        }
 
-       if len(message) == 0 {
-               message = "Update page '" + newWikiName + "'"
+       tree, err := gitRepo.WriteTree()
+       if err != nil {
+               log.Error("%v", err)
+               return err
        }
-       if err = git.AddChanges(localPath, true); err != nil {
-               return fmt.Errorf("AddChanges: %v", err)
-       } else if err = git.CommitChanges(localPath, git.CommitChangesOptions{
-               Committer: doer.NewGitSig(),
-               Message:   message,
-       }); err != nil {
-               return fmt.Errorf("CommitChanges: %v", err)
-       } else if err = git.Push(localPath, git.PushOptions{
+
+       commitTreeOpts := git.CommitTreeOpts{
+               Message: message,
+       }
+       if hasMasterBranch {
+               commitTreeOpts.Parents = []string{"HEAD"}
+       }
+       commitHash, err := gitRepo.CommitTree(doer.NewGitSig(), tree, commitTreeOpts)
+       if err != nil {
+               log.Error("%v", err)
+               return err
+       }
+
+       if err := git.Push(basePath, git.PushOptions{
                Remote: "origin",
-               Branch: "master",
+               Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
+               Env:    PushingEnvironment(doer, repo),
        }); err != nil {
+               log.Error("%v", err)
                return fmt.Errorf("Push: %v", err)
        }
 
@@ -210,31 +238,74 @@ func (repo *Repository) DeleteWikiPage(doer *User, wikiName string) (err error)
        wikiWorkingPool.CheckIn(com.ToStr(repo.ID))
        defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID))
 
-       localPath := repo.LocalWikiPath()
-       if err = discardLocalWikiChanges(localPath); err != nil {
-               return fmt.Errorf("discardLocalWikiChanges: %v", err)
-       } else if err = repo.updateLocalWiki(); err != nil {
-               return fmt.Errorf("UpdateLocalWiki: %v", err)
+       if err = repo.InitWiki(); err != nil {
+               return fmt.Errorf("InitWiki: %v", err)
+       }
+
+       basePath, err := CreateTemporaryPath("update-wiki")
+       if err != nil {
+               return err
        }
+       defer RemoveTemporaryPath(basePath)
 
-       filename := path.Join(localPath, WikiNameToFilename(wikiName))
+       if err := git.Clone(repo.WikiPath(), basePath, git.CloneRepoOptions{
+               Bare:   true,
+               Shared: true,
+               Branch: "master",
+       }); err != nil {
+               log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
+               return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err)
+       }
 
-       if err := os.Remove(filename); err != nil {
-               return fmt.Errorf("Failed to remove %s: %v", filename, err)
+       gitRepo, err := git.OpenRepository(basePath)
+       if err != nil {
+               log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
+               return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
        }
 
+       if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
+               log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
+               return fmt.Errorf("Unable to read HEAD tree to index in: %s %v", basePath, err)
+       }
+
+       wikiPath := WikiNameToFilename(wikiName)
+       filesInIndex, err := gitRepo.LsFiles(wikiPath)
+       found := false
+       for _, file := range filesInIndex {
+               if file == wikiPath {
+                       found = true
+                       break
+               }
+       }
+       if found {
+               err := gitRepo.RemoveFilesFromIndex(wikiPath)
+               if err != nil {
+                       return err
+               }
+       } else {
+               return os.ErrNotExist
+       }
+
+       // FIXME: The wiki doesn't have lfs support at present - if this changes need to check attributes here
+
+       tree, err := gitRepo.WriteTree()
+       if err != nil {
+               return err
+       }
        message := "Delete page '" + wikiName + "'"
 
-       if err = git.AddChanges(localPath, true); err != nil {
-               return fmt.Errorf("AddChanges: %v", err)
-       } else if err = git.CommitChanges(localPath, git.CommitChangesOptions{
-               Committer: doer.NewGitSig(),
-               Message:   message,
-       }); err != nil {
-               return fmt.Errorf("CommitChanges: %v", err)
-       } else if err = git.Push(localPath, git.PushOptions{
+       commitHash, err := gitRepo.CommitTree(doer.NewGitSig(), tree, git.CommitTreeOpts{
+               Message: message,
+               Parents: []string{"HEAD"},
+       })
+       if err != nil {
+               return err
+       }
+
+       if err := git.Push(basePath, git.PushOptions{
                Remote: "origin",
-               Branch: "master",
+               Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
+               Env:    PushingEnvironment(doer, repo),
        }); err != nil {
                return fmt.Errorf("Push: %v", err)
        }
index 5280b3ea01a268a35c57886a3cd51bbad4befeac..991a3d95b9036e28f9bcdf0ad256369c6b9d0cb8 100644 (file)
@@ -5,13 +5,12 @@
 package models
 
 import (
-       "path"
        "path/filepath"
        "testing"
 
+       "code.gitea.io/gitea/modules/git"
        "code.gitea.io/gitea/modules/setting"
 
-       "github.com/Unknwon/com"
        "github.com/stretchr/testify/assert"
 )
 
@@ -145,13 +144,6 @@ func TestRepository_InitWiki(t *testing.T) {
        assert.True(t, repo2.HasWiki())
 }
 
-func TestRepository_LocalWikiPath(t *testing.T) {
-       PrepareTestEnv(t)
-       repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
-       expected := filepath.Join(setting.AppDataPath, setting.Repository.Local.LocalWikiPath, "1")
-       assert.Equal(t, expected, repo.LocalWikiPath())
-}
-
 func TestRepository_AddWikiPage(t *testing.T) {
        assert.NoError(t, PrepareTestDatabase())
        const wikiContent = "This is the wiki content"
@@ -166,8 +158,15 @@ func TestRepository_AddWikiPage(t *testing.T) {
                t.Run("test wiki exist: "+wikiName, func(t *testing.T) {
                        t.Parallel()
                        assert.NoError(t, repo.AddWikiPage(doer, wikiName, wikiContent, commitMsg))
-                       expectedPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(wikiName))
-                       assert.True(t, com.IsExist(expectedPath))
+                       // Now need to show that the page has been added:
+                       gitRepo, err := git.OpenRepository(repo.WikiPath())
+                       assert.NoError(t, err)
+                       masterTree, err := gitRepo.GetTree("master")
+                       assert.NoError(t, err)
+                       wikiPath := WikiNameToFilename(wikiName)
+                       entry, err := masterTree.GetTreeEntryByPath(wikiPath)
+                       assert.NoError(t, err)
+                       assert.Equal(t, wikiPath, entry.Name(), "%s not addded correctly", wikiName)
                })
        }
 
@@ -200,11 +199,20 @@ func TestRepository_EditWikiPage(t *testing.T) {
        } {
                PrepareTestEnv(t)
                assert.NoError(t, repo.EditWikiPage(doer, "Home", newWikiName, newWikiContent, commitMsg))
-               newPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(newWikiName))
-               assert.True(t, com.IsExist(newPath))
+
+               // Now need to show that the page has been added:
+               gitRepo, err := git.OpenRepository(repo.WikiPath())
+               assert.NoError(t, err)
+               masterTree, err := gitRepo.GetTree("master")
+               assert.NoError(t, err)
+               wikiPath := WikiNameToFilename(newWikiName)
+               entry, err := masterTree.GetTreeEntryByPath(wikiPath)
+               assert.NoError(t, err)
+               assert.Equal(t, wikiPath, entry.Name(), "%s not editted correctly", newWikiName)
+
                if newWikiName != "Home" {
-                       oldPath := path.Join(repo.LocalWikiPath(), "Home.md")
-                       assert.False(t, com.IsExist(oldPath))
+                       _, err := masterTree.GetTreeEntryByPath("Home.md")
+                       assert.Error(t, err)
                }
        }
 }
@@ -214,6 +222,13 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
        repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
        doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
        assert.NoError(t, repo.DeleteWikiPage(doer, "Home"))
-       wikiPath := path.Join(repo.LocalWikiPath(), "Home.md")
-       assert.False(t, com.IsExist(wikiPath))
+
+       // Now need to show that the page has been added:
+       gitRepo, err := git.OpenRepository(repo.WikiPath())
+       assert.NoError(t, err)
+       masterTree, err := gitRepo.GetTree("master")
+       assert.NoError(t, err)
+       wikiPath := WikiNameToFilename("Home")
+       _, err = masterTree.GetTreeEntryByPath(wikiPath)
+       assert.Error(t, err)
 }
index 3602717702f1b7e204403d8fee545ee97b8b84f3..d6221ce26827bb1117606edadf5b251f8cdcc0e9 100644 (file)
@@ -52,9 +52,15 @@ func (c *Command) AddArguments(args ...string) *Command {
        return c
 }
 
-// RunInDirTimeoutPipeline executes the command in given directory with given timeout,
+// RunInDirTimeoutEnvPipeline executes the command in given directory with given timeout,
 // it pipes stdout and stderr to given io.Writer.
-func (c *Command) RunInDirTimeoutPipeline(timeout time.Duration, dir string, stdout, stderr io.Writer) error {
+func (c *Command) RunInDirTimeoutEnvPipeline(env []string, timeout time.Duration, dir string, stdout, stderr io.Writer) error {
+       return c.RunInDirTimeoutEnvFullPipeline(env, timeout, dir, stdout, stderr, nil)
+}
+
+// RunInDirTimeoutEnvFullPipeline executes the command in given directory with given timeout,
+// it pipes stdout and stderr to given io.Writer and passes in an io.Reader as stdin.
+func (c *Command) RunInDirTimeoutEnvFullPipeline(env []string, timeout time.Duration, dir string, stdout, stderr io.Writer, stdin io.Reader) error {
        if timeout == -1 {
                timeout = DefaultCommandExecutionTimeout
        }
@@ -69,9 +75,11 @@ func (c *Command) RunInDirTimeoutPipeline(timeout time.Duration, dir string, std
        defer cancel()
 
        cmd := exec.CommandContext(ctx, c.name, c.args...)
+       cmd.Env = env
        cmd.Dir = dir
        cmd.Stdout = stdout
        cmd.Stderr = stderr
+       cmd.Stdin = stdin
        if err := cmd.Start(); err != nil {
                return err
        }
@@ -83,12 +91,30 @@ func (c *Command) RunInDirTimeoutPipeline(timeout time.Duration, dir string, std
        return ctx.Err()
 }
 
+// RunInDirTimeoutPipeline executes the command in given directory with given timeout,
+// it pipes stdout and stderr to given io.Writer.
+func (c *Command) RunInDirTimeoutPipeline(timeout time.Duration, dir string, stdout, stderr io.Writer) error {
+       return c.RunInDirTimeoutEnvPipeline(nil, timeout, dir, stdout, stderr)
+}
+
+// RunInDirTimeoutFullPipeline executes the command in given directory with given timeout,
+// it pipes stdout and stderr to given io.Writer, and stdin from the given io.Reader
+func (c *Command) RunInDirTimeoutFullPipeline(timeout time.Duration, dir string, stdout, stderr io.Writer, stdin io.Reader) error {
+       return c.RunInDirTimeoutEnvFullPipeline(nil, timeout, dir, stdout, stderr, stdin)
+}
+
 // RunInDirTimeout executes the command in given directory with given timeout,
 // and returns stdout in []byte and error (combined with stderr).
 func (c *Command) RunInDirTimeout(timeout time.Duration, dir string) ([]byte, error) {
+       return c.RunInDirTimeoutEnv(nil, timeout, dir)
+}
+
+// RunInDirTimeoutEnv executes the command in given directory with given timeout,
+// and returns stdout in []byte and error (combined with stderr).
+func (c *Command) RunInDirTimeoutEnv(env []string, timeout time.Duration, dir string) ([]byte, error) {
        stdout := new(bytes.Buffer)
        stderr := new(bytes.Buffer)
-       if err := c.RunInDirTimeoutPipeline(timeout, dir, stdout, stderr); err != nil {
+       if err := c.RunInDirTimeoutEnvPipeline(env, timeout, dir, stdout, stderr); err != nil {
                return nil, concatenateError(err, stderr.String())
        }
 
@@ -101,7 +127,13 @@ func (c *Command) RunInDirTimeout(timeout time.Duration, dir string) ([]byte, er
 // RunInDirPipeline executes the command in given directory,
 // it pipes stdout and stderr to given io.Writer.
 func (c *Command) RunInDirPipeline(dir string, stdout, stderr io.Writer) error {
-       return c.RunInDirTimeoutPipeline(-1, dir, stdout, stderr)
+       return c.RunInDirFullPipeline(dir, stdout, stderr, nil)
+}
+
+// RunInDirFullPipeline executes the command in given directory,
+// it pipes stdout and stderr to given io.Writer.
+func (c *Command) RunInDirFullPipeline(dir string, stdout, stderr io.Writer, stdin io.Reader) error {
+       return c.RunInDirTimeoutFullPipeline(-1, dir, stdout, stderr, stdin)
 }
 
 // RunInDirBytes executes the command in given directory
@@ -113,7 +145,13 @@ func (c *Command) RunInDirBytes(dir string) ([]byte, error) {
 // RunInDir executes the command in given directory
 // and returns stdout in string and error (combined with stderr).
 func (c *Command) RunInDir(dir string) (string, error) {
-       stdout, err := c.RunInDirTimeout(-1, dir)
+       return c.RunInDirWithEnv(dir, nil)
+}
+
+// RunInDirWithEnv executes the command in given directory
+// and returns stdout in string and error (combined with stderr).
+func (c *Command) RunInDirWithEnv(dir string, env []string) (string, error) {
+       stdout, err := c.RunInDirTimeoutEnv(env, -1, dir)
        if err != nil {
                return "", err
        }
index 8355f8811f51afd5467583f0610522094abddcc5..4be31641307952d0537fa4944aed6ad531d20bd5 100644 (file)
@@ -109,11 +109,13 @@ func OpenRepository(repoPath string) (*Repository, error) {
 
 // CloneRepoOptions options when clone a repository
 type CloneRepoOptions struct {
-       Timeout time.Duration
-       Mirror  bool
-       Bare    bool
-       Quiet   bool
-       Branch  string
+       Timeout    time.Duration
+       Mirror     bool
+       Bare       bool
+       Quiet      bool
+       Branch     string
+       Shared     bool
+       NoCheckout bool
 }
 
 // Clone clones original repository to target path.
@@ -133,10 +135,17 @@ func Clone(from, to string, opts CloneRepoOptions) (err error) {
        if opts.Quiet {
                cmd.AddArguments("--quiet")
        }
+       if opts.Shared {
+               cmd.AddArguments("-s")
+       }
+       if opts.NoCheckout {
+               cmd.AddArguments("--no-checkout")
+       }
+
        if len(opts.Branch) > 0 {
                cmd.AddArguments("-b", opts.Branch)
        }
-       cmd.AddArguments(from, to)
+       cmd.AddArguments("--", from, to)
 
        if opts.Timeout <= 0 {
                opts.Timeout = -1
@@ -181,6 +190,7 @@ type PushOptions struct {
        Remote string
        Branch string
        Force  bool
+       Env    []string
 }
 
 // Push pushs local commits to given remote branch.
@@ -190,7 +200,7 @@ func Push(repoPath string, opts PushOptions) error {
                cmd.AddArguments("-f")
        }
        cmd.AddArguments(opts.Remote, opts.Branch)
-       _, err := cmd.RunInDir(repoPath)
+       _, err := cmd.RunInDirWithEnv(repoPath, opts.Env)
        return err
 }
 
index 83689ee9dc03d5dddd08a5f8f1721a6304ac191b..116bdbee823c728f82a32d11d7f25ec80a821e28 100644 (file)
@@ -17,7 +17,7 @@ const BranchPrefix = "refs/heads/"
 
 // IsReferenceExist returns true if given reference exists in the repository.
 func IsReferenceExist(repoPath, name string) bool {
-       _, err := NewCommand("show-ref", "--verify", name).RunInDir(repoPath)
+       _, err := NewCommand("show-ref", "--verify", "--", name).RunInDir(repoPath)
        return err == nil
 }
 
@@ -145,9 +145,9 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro
 }
 
 // CreateBranch create a new branch
-func (repo *Repository) CreateBranch(branch, newBranch string) error {
+func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error {
        cmd := NewCommand("branch")
-       cmd.AddArguments(branch, newBranch)
+       cmd.AddArguments("--", branch, oldbranchOrCommit)
 
        _, err := cmd.RunInDir(repo.Path)
 
diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go
new file mode 100644 (file)
index 0000000..4d26563
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package git
+
+import (
+       "bytes"
+       "strings"
+)
+
+// ReadTreeToIndex reads a treeish to the index
+func (repo *Repository) ReadTreeToIndex(treeish string) error {
+       if len(treeish) != 40 {
+               res, err := NewCommand("rev-parse", treeish).RunInDir(repo.Path)
+               if err != nil {
+                       return err
+               }
+               if len(res) > 0 {
+                       treeish = res[:len(res)-1]
+               }
+       }
+       id, err := NewIDFromString(treeish)
+       if err != nil {
+               return err
+       }
+       return repo.readTreeToIndex(id)
+}
+
+func (repo *Repository) readTreeToIndex(id SHA1) error {
+       _, err := NewCommand("read-tree", id.String()).RunInDir(repo.Path)
+       if err != nil {
+               return err
+       }
+       return nil
+}
+
+// EmptyIndex empties the index
+func (repo *Repository) EmptyIndex() error {
+       _, err := NewCommand("read-tree", "--empty").RunInDir(repo.Path)
+       return err
+}
+
+// LsFiles checks if the given filenames are in the index
+func (repo *Repository) LsFiles(filenames ...string) ([]string, error) {
+       cmd := NewCommand("ls-files", "-z", "--")
+       for _, arg := range filenames {
+               if arg != "" {
+                       cmd.AddArguments(arg)
+               }
+       }
+       res, err := cmd.RunInDirBytes(repo.Path)
+       if err != nil {
+               return nil, err
+       }
+       filelist := make([]string, 0, len(filenames))
+       for _, line := range bytes.Split(res, []byte{'\000'}) {
+               filelist = append(filelist, string(line))
+       }
+
+       return filelist, err
+}
+
+// RemoveFilesFromIndex removes given filenames from the index - it does not check whether they are present.
+func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
+       cmd := NewCommand("update-index", "--remove", "-z", "--index-info")
+       stdout := new(bytes.Buffer)
+       stderr := new(bytes.Buffer)
+       buffer := new(bytes.Buffer)
+       for _, file := range filenames {
+               if file != "" {
+                       buffer.WriteString("0 0000000000000000000000000000000000000000\t")
+                       buffer.WriteString(file)
+                       buffer.WriteByte('\000')
+               }
+       }
+       return cmd.RunInDirFullPipeline(repo.Path, stdout, stderr, bytes.NewReader(buffer.Bytes()))
+}
+
+// AddObjectToIndex adds the provided object hash to the index at the provided filename
+func (repo *Repository) AddObjectToIndex(mode string, object SHA1, filename string) error {
+       cmd := NewCommand("update-index", "--add", "--replace", "--cacheinfo", mode, object.String(), filename)
+       _, err := cmd.RunInDir(repo.Path)
+       return err
+}
+
+// WriteTree writes the current index as a tree to the object db and returns its hash
+func (repo *Repository) WriteTree() (*Tree, error) {
+       res, err := NewCommand("write-tree").RunInDir(repo.Path)
+       if err != nil {
+               return nil, err
+       }
+       id, err := NewIDFromString(strings.TrimSpace(res))
+       if err != nil {
+               return nil, err
+       }
+       return NewTree(repo, id), nil
+}
index 3be8400d22210aa088050410dd7ab2392640f44d..67060e30b0b46e5bea6221d731fdcfe0c4f9afb0 100644 (file)
@@ -4,6 +4,12 @@
 
 package git
 
+import (
+       "bytes"
+       "io"
+       "strings"
+)
+
 // ObjectType git object type
 type ObjectType string
 
@@ -17,3 +23,24 @@ const (
        // ObjectTag tag object type
        ObjectTag ObjectType = "tag"
 )
+
+// HashObject takes a reader and returns SHA1 hash for that reader
+func (repo *Repository) HashObject(reader io.Reader) (SHA1, error) {
+       idStr, err := repo.hashObject(reader)
+       if err != nil {
+               return SHA1{}, err
+       }
+       return NewIDFromString(idStr)
+}
+
+func (repo *Repository) hashObject(reader io.Reader) (string, error) {
+       cmd := NewCommand("hash-object", "-w", "--stdin")
+       stdout := new(bytes.Buffer)
+       stderr := new(bytes.Buffer)
+       err := cmd.RunInDirFullPipeline(repo.Path, stdout, stderr, reader)
+
+       if err != nil {
+               return "", err
+       }
+       return strings.TrimSpace(stdout.String()), nil
+}
index 8bb729174428d4b467d4b26071a9cfc1ff1627cc..7d32d3685ccb23b08600f42f13d859a102e502b6 100644 (file)
@@ -6,6 +6,11 @@
 package git
 
 import (
+       "fmt"
+       "os"
+       "strings"
+       "time"
+
        "gopkg.in/src-d/go-git.v4/plumbing"
 )
 
@@ -47,3 +52,48 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
        treeObject.ResolvedID = resolvedID
        return treeObject, nil
 }
+
+// CommitTreeOpts represents the possible options to CommitTree
+type CommitTreeOpts struct {
+       Parents   []string
+       Message   string
+       KeyID     string
+       NoGPGSign bool
+}
+
+// CommitTree creates a commit from a given tree id for the user with provided message
+func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
+       commitTimeStr := time.Now().Format(time.UnixDate)
+
+       // Because this may call hooks we should pass in the environment
+       env := append(os.Environ(),
+               "GIT_AUTHOR_NAME="+sig.Name,
+               "GIT_AUTHOR_EMAIL="+sig.Email,
+               "GIT_AUTHOR_DATE="+commitTimeStr,
+               "GIT_COMMITTER_NAME="+sig.Name,
+               "GIT_COMMITTER_EMAIL="+sig.Email,
+               "GIT_COMMITTER_DATE="+commitTimeStr,
+       )
+       cmd := NewCommand("commit-tree", tree.ID.String())
+
+       for _, parent := range opts.Parents {
+               cmd.AddArguments("-p", parent)
+       }
+
+       cmd.AddArguments("-m", opts.Message)
+
+       if opts.KeyID != "" {
+               cmd.AddArguments(fmt.Sprintf("-S%s", opts.KeyID))
+       }
+
+       if opts.NoGPGSign {
+               cmd.AddArguments("--no-gpg-sign")
+       }
+
+       res, err := cmd.RunInDirWithEnv(repo.Path, env)
+
+       if err != nil {
+               return SHA1{}, err
+       }
+       return NewIDFromString(strings.TrimSpace(res))
+}
diff --git a/modules/repofiles/delete_test.go b/modules/repofiles/delete_test.go
deleted file mode 100644 (file)
index 9d03406..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2019 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repofiles
-
-import (
-       "testing"
-
-       "code.gitea.io/gitea/models"
-       api "code.gitea.io/gitea/modules/structs"
-       "code.gitea.io/gitea/modules/test"
-
-       "github.com/stretchr/testify/assert"
-)
-
-func getDeleteRepoFileOptions(repo *models.Repository) *DeleteRepoFileOptions {
-       return &DeleteRepoFileOptions{
-               LastCommitID: "",
-               OldBranch:    repo.DefaultBranch,
-               NewBranch:    repo.DefaultBranch,
-               TreePath:     "README.md",
-               Message:      "Deletes README.md",
-               SHA:          "4b4851ad51df6a7d9f25c979345979eaeb5b349f",
-               Author:       nil,
-               Committer:    nil,
-       }
-}
-
-func getExpectedDeleteFileResponse() *api.FileResponse {
-       return &api.FileResponse{
-               Content: nil,
-               Commit: &api.FileCommitResponse{
-                       CommitMeta: api.CommitMeta{
-                               URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d",
-                               SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
-                       },
-                       HTMLURL: "https://try.gitea.io/user2/repo1/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d",
-                       Author: &api.CommitUser{
-                               Identity: api.Identity{
-                                       Name:  "user1",
-                                       Email: "address1@example.com",
-                               },
-                               Date: "2017-03-19T20:47:59Z",
-                       },
-                       Committer: &api.CommitUser{
-                               Identity: api.Identity{
-                                       Name:  "Ethan Koenig",
-                                       Email: "ethantkoenig@gmail.com",
-                               },
-                               Date: "2017-03-19T20:47:59Z",
-                       },
-                       Parents: []*api.CommitMeta{},
-                       Message: "Initial commit\n",
-                       Tree: &api.CommitMeta{
-                               URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/trees/2a2f1d4670728a2e10049e345bd7a276468beab6",
-                               SHA: "2a2f1d4670728a2e10049e345bd7a276468beab6",
-                       },
-               },
-               Verification: &api.PayloadCommitVerification{
-                       Verified:  false,
-                       Reason:    "",
-                       Signature: "",
-                       Payload:   "",
-               },
-       }
-}
-
-func TestDeleteRepoFile(t *testing.T) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-       opts := getDeleteRepoFileOptions(repo)
-
-       t.Run("Delete README.md file", func(t *testing.T) {
-               fileResponse, err := DeleteRepoFile(repo, doer, opts)
-               assert.Nil(t, err)
-               expectedFileResponse := getExpectedDeleteFileResponse()
-               assert.EqualValues(t, expectedFileResponse, fileResponse)
-       })
-
-       t.Run("Verify README.md has been deleted", func(t *testing.T) {
-               fileResponse, err := DeleteRepoFile(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) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-       opts := getDeleteRepoFileOptions(repo)
-       opts.OldBranch = ""
-       opts.NewBranch = ""
-
-       t.Run("Delete README.md without Branch Name", func(t *testing.T) {
-               fileResponse, err := DeleteRepoFile(repo, doer, opts)
-               assert.Nil(t, err)
-               expectedFileResponse := getExpectedDeleteFileResponse()
-               assert.EqualValues(t, expectedFileResponse, fileResponse)
-       })
-}
-
-func TestDeleteRepoFileErrors(t *testing.T) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-
-       t.Run("Bad branch", func(t *testing.T) {
-               opts := getDeleteRepoFileOptions(repo)
-               opts.OldBranch = "bad_branch"
-               fileResponse, err := DeleteRepoFile(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 := DeleteRepoFile(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 := DeleteRepoFile(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 := DeleteRepoFile(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 := DeleteRepoFile(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)
-       })
-}
index 46e03f5650232b65a506e0d2be9465fa4e6faaeb..ec35628676fcfe081bea8eaaa67b78c5735e7bae 100644 (file)
@@ -11,17 +11,15 @@ import (
        "io"
        "os"
        "os/exec"
-       "path"
        "regexp"
        "strings"
        "time"
 
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/modules/git"
+       "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/process"
        "code.gitea.io/gitea/modules/setting"
-
-       "github.com/Unknwon/com"
 )
 
 // TemporaryUploadRepository is a type to wrap our upload repositories as a shallow clone
@@ -33,13 +31,9 @@ type TemporaryUploadRepository struct {
 
 // NewTemporaryUploadRepository creates a new temporary upload repository
 func NewTemporaryUploadRepository(repo *models.Repository) (*TemporaryUploadRepository, error) {
-       timeStr := com.ToStr(time.Now().Nanosecond()) // SHOULD USE SOMETHING UNIQUE
-       basePath := path.Join(models.LocalCopyPath(), "upload-"+timeStr+".git")
-       if err := os.MkdirAll(path.Dir(basePath), os.ModePerm); err != nil {
-               return nil, fmt.Errorf("failed to create dir %s: %v", basePath, err)
-       }
-       if repo.RepoPath() == "" {
-               return nil, fmt.Errorf("no path to repository on system")
+       basePath, err := models.CreateTemporaryPath("upload")
+       if err != nil {
+               return nil, err
        }
        t := &TemporaryUploadRepository{repo: repo, basePath: basePath}
        return t, nil
@@ -47,8 +41,8 @@ func NewTemporaryUploadRepository(repo *models.Repository) (*TemporaryUploadRepo
 
 // Close the repository cleaning up all files
 func (t *TemporaryUploadRepository) Close() {
-       if _, err := os.Stat(t.basePath); !os.IsNotExist(err) {
-               os.RemoveAll(t.basePath)
+       if err := models.RemoveTemporaryPath(t.basePath); err != nil {
+               log.Error("Failed to remove temporary path %s: %v", t.basePath, err)
        }
 }
 
@@ -282,27 +276,8 @@ func (t *TemporaryUploadRepository) CommitTree(author, committer *models.User, t
 
 // Push the provided commitHash to the repository branch by the provided user
 func (t *TemporaryUploadRepository) Push(doer *models.User, commitHash string, branch string) error {
-       isWiki := "false"
-       if strings.HasSuffix(t.repo.Name, ".wiki") {
-               isWiki = "true"
-       }
-
-       sig := doer.NewGitSig()
-
-       // FIXME: Should we add SSH_ORIGINAL_COMMAND to this
        // Because calls hooks we need to pass in the environment
-       env := append(os.Environ(),
-               "GIT_AUTHOR_NAME="+sig.Name,
-               "GIT_AUTHOR_EMAIL="+sig.Email,
-               "GIT_COMMITTER_NAME="+sig.Name,
-               "GIT_COMMITTER_EMAIL="+sig.Email,
-               models.EnvRepoName+"="+t.repo.Name,
-               models.EnvRepoUsername+"="+t.repo.OwnerName,
-               models.EnvRepoIsWiki+"="+isWiki,
-               models.EnvPusherName+"="+doer.Name,
-               models.EnvPusherID+"="+fmt.Sprintf("%d", doer.ID),
-               models.ProtectedBranchRepoID+"="+fmt.Sprintf("%d", t.repo.ID),
-       )
+       env := models.PushingEnvironment(doer, t.repo)
 
        if _, stderr, err := process.GetManager().ExecDirEnv(5*time.Minute,
                t.basePath,
diff --git a/modules/repofiles/update_test.go b/modules/repofiles/update_test.go
deleted file mode 100644 (file)
index a3a0b0a..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-// Copyright 2019 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package repofiles
-
-import (
-       "testing"
-       "time"
-
-       "code.gitea.io/gitea/models"
-       "code.gitea.io/gitea/modules/git"
-       api "code.gitea.io/gitea/modules/structs"
-       "code.gitea.io/gitea/modules/test"
-
-       "github.com/stretchr/testify/assert"
-)
-
-func getCreateRepoFileOptions(repo *models.Repository) *UpdateRepoFileOptions {
-       return &UpdateRepoFileOptions{
-               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 *models.Repository) *UpdateRepoFileOptions {
-       return &UpdateRepoFileOptions{
-               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 getExpectedFileResponseForCreate(commitID string) *api.FileResponse {
-       return &api.FileResponse{
-               Content: &api.FileContentResponse{
-                       Name:        "file.txt",
-                       Path:        "new/file.txt",
-                       SHA:         "103ff9234cefeee5ec5361d22b49fbb04d385885",
-                       Size:        18,
-                       URL:         "https://try.gitea.io/api/v1/repos/user2/repo1/contents/new/file.txt",
-                       HTMLURL:     "https://try.gitea.io/user2/repo1/blob/master/new/file.txt",
-                       GitURL:      "https://try.gitea.io/api/v1/repos/user2/repo1/git/blobs/103ff9234cefeee5ec5361d22b49fbb04d385885",
-                       DownloadURL: "https://try.gitea.io/user2/repo1/raw/branch/master/new/file.txt",
-                       Type:        "blob",
-                       Links: &api.FileLinksResponse{
-                               Self:    "https://try.gitea.io/api/v1/repos/user2/repo1/contents/new/file.txt",
-                               GitURL:  "https://try.gitea.io/api/v1/repos/user2/repo1/git/blobs/103ff9234cefeee5ec5361d22b49fbb04d385885",
-                               HTMLURL: "https://try.gitea.io/user2/repo1/blob/master/new/file.txt",
-                       },
-               },
-               Commit: &api.FileCommitResponse{
-                       CommitMeta: api.CommitMeta{
-                               URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/commits/" + commitID,
-                               SHA: commitID,
-                       },
-                       HTMLURL: "https://try.gitea.io/user2/repo1/commit/" + commitID,
-                       Author: &api.CommitUser{
-                               Identity: api.Identity{
-                                       Name:  "User Two",
-                                       Email: "user2@",
-                               },
-                               Date: time.Now().UTC().Format(time.RFC3339),
-                       },
-                       Committer: &api.CommitUser{
-                               Identity: api.Identity{
-                                       Name:  "User Two",
-                                       Email: "user2@",
-                               },
-                               Date: time.Now().UTC().Format(time.RFC3339),
-                       },
-                       Parents: []*api.CommitMeta{
-                               {
-                                       URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d",
-                                       SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
-                               },
-                       },
-                       Message: "Updates README.md\n",
-                       Tree: &api.CommitMeta{
-                               URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc",
-                               SHA: "f93e3a1a1525fb5b91020git dda86e44810c87a2d7bc",
-                       },
-               },
-               Verification: &api.PayloadCommitVerification{
-                       Verified:  false,
-                       Reason:    "unsigned",
-                       Signature: "",
-                       Payload:   "",
-               },
-       }
-}
-
-func getExpectedFileResponseForUpdate(commitID string) *api.FileResponse {
-       return &api.FileResponse{
-               Content: &api.FileContentResponse{
-                       Name:        "README.md",
-                       Path:        "README.md",
-                       SHA:         "dbf8d00e022e05b7e5cf7e535de857de57925647",
-                       Size:        43,
-                       URL:         "https://try.gitea.io/api/v1/repos/user2/repo1/contents/README.md",
-                       HTMLURL:     "https://try.gitea.io/user2/repo1/blob/master/README.md",
-                       GitURL:      "https://try.gitea.io/api/v1/repos/user2/repo1/git/blobs/dbf8d00e022e05b7e5cf7e535de857de57925647",
-                       DownloadURL: "https://try.gitea.io/user2/repo1/raw/branch/master/README.md",
-                       Type:        "blob",
-                       Links: &api.FileLinksResponse{
-                               Self:    "https://try.gitea.io/api/v1/repos/user2/repo1/contents/README.md",
-                               GitURL:  "https://try.gitea.io/api/v1/repos/user2/repo1/git/blobs/dbf8d00e022e05b7e5cf7e535de857de57925647",
-                               HTMLURL: "https://try.gitea.io/user2/repo1/blob/master/README.md",
-                       },
-               },
-               Commit: &api.FileCommitResponse{
-                       CommitMeta: api.CommitMeta{
-                               URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/commits/" + commitID,
-                               SHA: commitID,
-                       },
-                       HTMLURL: "https://try.gitea.io/user2/repo1/commit/" + commitID,
-                       Author: &api.CommitUser{
-                               Identity: api.Identity{
-                                       Name:  "User Two",
-                                       Email: "user2@",
-                               },
-                               Date: time.Now().UTC().Format(time.RFC3339),
-                       },
-                       Committer: &api.CommitUser{
-                               Identity: api.Identity{
-                                       Name:  "User Two",
-                                       Email: "user2@",
-                               },
-                               Date: time.Now().UTC().Format(time.RFC3339),
-                       },
-                       Parents: []*api.CommitMeta{
-                               {
-                                       URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d",
-                                       SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
-                               },
-                       },
-                       Message: "Updates README.md\n",
-                       Tree: &api.CommitMeta{
-                               URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/trees/f93e3a1a1525fb5b91020da86e44810c87a2d7bc",
-                               SHA: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc",
-                       },
-               },
-               Verification: &api.PayloadCommitVerification{
-                       Verified:  false,
-                       Reason:    "unsigned",
-                       Signature: "",
-                       Payload:   "",
-               },
-       }
-}
-
-func TestCreateOrUpdateRepoFileForCreate(t *testing.T) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-       opts := getCreateRepoFileOptions(repo)
-
-       // test
-       fileResponse, err := CreateOrUpdateRepoFile(repo, doer, opts)
-
-       // asserts
-       assert.Nil(t, err)
-       gitRepo, _ := git.OpenRepository(repo.RepoPath())
-       commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
-       expectedFileResponse := getExpectedFileResponseForCreate(commitID)
-       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)
-}
-
-func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-       opts := getUpdateRepoFileOptions(repo)
-
-       // test
-       fileResponse, err := CreateOrUpdateRepoFile(repo, doer, opts)
-
-       // asserts
-       assert.Nil(t, err)
-       gitRepo, _ := git.OpenRepository(repo.RepoPath())
-       commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
-       expectedFileResponse := getExpectedFileResponseForUpdate(commitID)
-       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)
-}
-
-func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-       opts := getUpdateRepoFileOptions(repo)
-       suffix := "_new"
-       opts.FromTreePath = "README.md"
-       opts.TreePath = "README.md" + suffix // new file name, README.md_new
-
-       // test
-       fileResponse, err := CreateOrUpdateRepoFile(repo, doer, opts)
-
-       // asserts
-       assert.Nil(t, err)
-       gitRepo, _ := git.OpenRepository(repo.RepoPath())
-       commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
-       expectedFileResponse := getExpectedFileResponseForUpdate(commit.ID.String())
-       // assert that the old file no longer exists in the last commit of the branch
-       fromEntry, err := commit.GetTreeEntryByPath(opts.FromTreePath)
-       toEntry, err := commit.GetTreeEntryByPath(opts.TreePath)
-       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+suffix, fileResponse.Content.Name)
-       assert.EqualValues(t, expectedFileResponse.Content.Path+suffix, fileResponse.Content.Path)
-       assert.EqualValues(t, expectedFileResponse.Content.URL+suffix, fileResponse.Content.URL)
-       assert.EqualValues(t, expectedFileResponse.Commit.SHA, fileResponse.Commit.SHA)
-       assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
-}
-
-// Test opts with branch names removed, should get same results as above test
-func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-       opts := getUpdateRepoFileOptions(repo)
-       opts.OldBranch = ""
-       opts.NewBranch = ""
-
-       // test
-       fileResponse, err := CreateOrUpdateRepoFile(repo, doer, opts)
-
-       // asserts
-       assert.Nil(t, err)
-       gitRepo, _ := git.OpenRepository(repo.RepoPath())
-       commitID, _ := gitRepo.GetBranchCommitID(repo.DefaultBranch)
-       expectedFileResponse := getExpectedFileResponseForUpdate(commitID)
-       assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
-}
-
-func TestCreateOrUpdateRepoFileErrors(t *testing.T) {
-       // setup
-       models.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)
-       repo := ctx.Repo.Repository
-       doer := ctx.User
-
-       t.Run("bad branch", func(t *testing.T) {
-               opts := getUpdateRepoFileOptions(repo)
-               opts.OldBranch = "bad_branch"
-               fileResponse, err := CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
-               origSHA := opts.SHA
-               opts.SHA = "bad_sha"
-               fileResponse, err := CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
-               opts.NewBranch = "develop"
-               fileResponse, err := CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
-               opts.TreePath = ""
-               fileResponse, err := CreateOrUpdateRepoFile(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 := getUpdateRepoFileOptions(repo)
-               opts.TreePath = ".git"
-               fileResponse, err := CreateOrUpdateRepoFile(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)
-       })
-
-       t.Run("create file that already exists", func(t *testing.T) {
-               opts := getCreateRepoFileOptions(repo)
-               opts.TreePath = "README.md" //already exists
-               fileResponse, err := CreateOrUpdateRepoFile(repo, doer, opts)
-               assert.Nil(t, fileResponse)
-               assert.Error(t, err)
-               expectedError := "repository file already exists [path: " + opts.TreePath + "]"
-               assert.EqualError(t, err, expectedError)
-       })
-}
index f47661efdfd3b278d638b8affb90d5ca0b1018b0..98e3d6e82624dcac75c8b4f93d14b8eb4463677f 100644 (file)
@@ -53,7 +53,6 @@ var (
                // Repository local settings
                Local struct {
                        LocalCopyPath string
-                       LocalWikiPath string
                } `ini:"-"`
 
                // Pull request settings
@@ -105,10 +104,8 @@ var (
                // Repository local settings
                Local: struct {
                        LocalCopyPath string
-                       LocalWikiPath string
                }{
                        LocalCopyPath: "tmp/local-repo",
-                       LocalWikiPath: "tmp/local-wiki",
                },
 
                // Pull request settings
index 8b987f0a60295782edc594a4d96889dba262bdb2..ae87aa5b3a09d47db2421a20afcb150e8ff50119 100644 (file)
@@ -74,12 +74,6 @@ func DeleteBranchPost(ctx *context.Context) {
                return
        }
 
-       // Delete branch in local copy if it exists
-       if err := ctx.Repo.Repository.DeleteLocalBranch(branchName); err != nil {
-               ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", branchName))
-               return
-       }
-
        ctx.Flash.Success(ctx.Tr("repo.branch.deletion_success", branchName))
 }