gitea源码

git_push_test.go 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "fmt"
  6. "net/url"
  7. "testing"
  8. auth_model "code.gitea.io/gitea/models/auth"
  9. "code.gitea.io/gitea/models/db"
  10. git_model "code.gitea.io/gitea/models/git"
  11. "code.gitea.io/gitea/models/unittest"
  12. user_model "code.gitea.io/gitea/models/user"
  13. "code.gitea.io/gitea/modules/git"
  14. "code.gitea.io/gitea/modules/git/gitcmd"
  15. repo_service "code.gitea.io/gitea/services/repository"
  16. "github.com/stretchr/testify/assert"
  17. "github.com/stretchr/testify/require"
  18. )
  19. func TestGitPush(t *testing.T) {
  20. onGiteaRun(t, testGitPush)
  21. }
  22. func testGitPush(t *testing.T, u *url.URL) {
  23. t.Run("Push branches at once", func(t *testing.T) {
  24. runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
  25. for i := range 100 {
  26. branchName := fmt.Sprintf("branch-%d", i)
  27. pushed = append(pushed, branchName)
  28. doGitCreateBranch(gitPath, branchName)(t)
  29. }
  30. pushed = append(pushed, "master")
  31. doGitPushTestRepository(gitPath, "origin", "--all")(t)
  32. return pushed, deleted
  33. })
  34. })
  35. t.Run("Push branches exists", func(t *testing.T) {
  36. runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
  37. for i := range 10 {
  38. branchName := fmt.Sprintf("branch-%d", i)
  39. if i < 5 {
  40. pushed = append(pushed, branchName)
  41. }
  42. doGitCreateBranch(gitPath, branchName)(t)
  43. }
  44. // only push master and the first 5 branches
  45. pushed = append(pushed, "master")
  46. args := append([]string{"origin"}, pushed...)
  47. doGitPushTestRepository(gitPath, args...)(t)
  48. pushed = pushed[:0]
  49. // do some changes for the first 5 branches created above
  50. for i := range 5 {
  51. branchName := fmt.Sprintf("branch-%d", i)
  52. pushed = append(pushed, branchName)
  53. doGitAddSomeCommits(gitPath, branchName)(t)
  54. }
  55. for i := 5; i < 10; i++ {
  56. pushed = append(pushed, fmt.Sprintf("branch-%d", i))
  57. }
  58. pushed = append(pushed, "master")
  59. // push all, so that master is not changed
  60. doGitPushTestRepository(gitPath, "origin", "--all")(t)
  61. return pushed, deleted
  62. })
  63. })
  64. t.Run("Push branches one by one", func(t *testing.T) {
  65. runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
  66. for i := range 100 {
  67. branchName := fmt.Sprintf("branch-%d", i)
  68. doGitCreateBranch(gitPath, branchName)(t)
  69. doGitPushTestRepository(gitPath, "origin", branchName)(t)
  70. pushed = append(pushed, branchName)
  71. }
  72. return pushed, deleted
  73. })
  74. })
  75. t.Run("Push branch with options", func(t *testing.T) {
  76. runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
  77. branchName := "branch-with-options"
  78. doGitCreateBranch(gitPath, branchName)(t)
  79. doGitPushTestRepository(gitPath, "origin", branchName, "-o", "repo.private=true", "-o", "repo.template=true")(t)
  80. pushed = append(pushed, branchName)
  81. return pushed, deleted
  82. })
  83. })
  84. t.Run("Delete branches", func(t *testing.T) {
  85. runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
  86. doGitPushTestRepository(gitPath, "origin", "master")(t) // make sure master is the default branch instead of a branch we are going to delete
  87. pushed = append(pushed, "master")
  88. for i := range 100 {
  89. branchName := fmt.Sprintf("branch-%d", i)
  90. pushed = append(pushed, branchName)
  91. doGitCreateBranch(gitPath, branchName)(t)
  92. }
  93. doGitPushTestRepository(gitPath, "origin", "--all")(t)
  94. for i := range 10 {
  95. branchName := fmt.Sprintf("branch-%d", i)
  96. doGitPushTestRepository(gitPath, "origin", "--delete", branchName)(t)
  97. deleted = append(deleted, branchName)
  98. }
  99. return pushed, deleted
  100. })
  101. })
  102. t.Run("Push to deleted branch", func(t *testing.T) {
  103. runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
  104. doGitPushTestRepository(gitPath, "origin", "master")(t) // make sure master is the default branch instead of a branch we are going to delete
  105. pushed = append(pushed, "master")
  106. doGitCreateBranch(gitPath, "branch-1")(t)
  107. doGitPushTestRepository(gitPath, "origin", "branch-1")(t)
  108. pushed = append(pushed, "branch-1")
  109. // delete and restore
  110. doGitPushTestRepository(gitPath, "origin", "--delete", "branch-1")(t)
  111. doGitPushTestRepository(gitPath, "origin", "branch-1")(t)
  112. return pushed, deleted
  113. })
  114. })
  115. }
  116. func runTestGitPush(t *testing.T, u *url.URL, gitOperation func(t *testing.T, gitPath string) (pushed, deleted []string)) {
  117. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  118. repo, err := repo_service.CreateRepository(t.Context(), user, user, repo_service.CreateRepoOptions{
  119. Name: "repo-to-push",
  120. Description: "test git push",
  121. AutoInit: false,
  122. DefaultBranch: "main",
  123. IsPrivate: false,
  124. })
  125. require.NoError(t, err)
  126. require.NotEmpty(t, repo)
  127. gitPath := t.TempDir()
  128. doGitInitTestRepository(gitPath)(t)
  129. oldPath := u.Path
  130. oldUser := u.User
  131. defer func() {
  132. u.Path = oldPath
  133. u.User = oldUser
  134. }()
  135. u.Path = repo.FullName() + ".git"
  136. u.User = url.UserPassword(user.LowerName, userPassword)
  137. doGitAddRemote(gitPath, "origin", u)(t)
  138. gitRepo, err := git.OpenRepository(t.Context(), gitPath)
  139. require.NoError(t, err)
  140. defer gitRepo.Close()
  141. pushedBranches, deletedBranches := gitOperation(t, gitPath)
  142. dbBranches := make([]*git_model.Branch, 0)
  143. require.NoError(t, db.GetEngine(t.Context()).Where("repo_id=?", repo.ID).Find(&dbBranches))
  144. assert.Lenf(t, dbBranches, len(pushedBranches), "mismatched number of branches in db")
  145. dbBranchesMap := make(map[string]*git_model.Branch, len(dbBranches))
  146. for _, branch := range dbBranches {
  147. dbBranchesMap[branch.Name] = branch
  148. }
  149. deletedBranchesMap := make(map[string]bool, len(deletedBranches))
  150. for _, branchName := range deletedBranches {
  151. deletedBranchesMap[branchName] = true
  152. }
  153. for _, branchName := range pushedBranches {
  154. branch, ok := dbBranchesMap[branchName]
  155. deleted := deletedBranchesMap[branchName]
  156. assert.True(t, ok, "branch %s not found in database", branchName)
  157. assert.Equal(t, deleted, branch.IsDeleted, "IsDeleted of %s is %v, but it's expected to be %v", branchName, branch.IsDeleted, deleted)
  158. commitID, err := gitRepo.GetBranchCommitID(branchName)
  159. require.NoError(t, err)
  160. assert.Equal(t, commitID, branch.CommitID)
  161. }
  162. require.NoError(t, repo_service.DeleteRepositoryDirectly(t.Context(), repo.ID))
  163. }
  164. func TestPushPullRefs(t *testing.T) {
  165. onGiteaRun(t, func(t *testing.T, u *url.URL) {
  166. baseAPITestContext := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
  167. u.Path = baseAPITestContext.GitPath()
  168. u.User = url.UserPassword("user2", userPassword)
  169. dstPath := t.TempDir()
  170. doGitClone(dstPath, u)(t)
  171. cmd := gitcmd.NewCommand("push", "--delete", "origin", "refs/pull/2/head")
  172. stdout, stderr, err := cmd.RunStdString(t.Context(), &gitcmd.RunOpts{
  173. Dir: dstPath,
  174. })
  175. assert.Error(t, err)
  176. assert.Empty(t, stdout)
  177. assert.NotContains(t, stderr, "[deleted]", "stderr: %s", stderr)
  178. })
  179. }