gitea源码

repo_branch_test.go 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "path"
  9. "strings"
  10. "testing"
  11. repo_model "code.gitea.io/gitea/models/repo"
  12. "code.gitea.io/gitea/models/unittest"
  13. "code.gitea.io/gitea/modules/test"
  14. "code.gitea.io/gitea/modules/translation"
  15. "code.gitea.io/gitea/tests"
  16. "github.com/PuerkitoBio/goquery"
  17. "github.com/stretchr/testify/assert"
  18. )
  19. func testCreateBranch(t testing.TB, session *TestSession, user, repo, oldRefSubURL, newBranchName string, expectedStatus int) string {
  20. csrf := GetUserCSRFToken(t, session)
  21. req := NewRequestWithValues(t, "POST", path.Join(user, repo, "branches/_new", oldRefSubURL), map[string]string{
  22. "_csrf": csrf,
  23. "new_branch_name": newBranchName,
  24. })
  25. resp := session.MakeRequest(t, req, expectedStatus)
  26. if expectedStatus != http.StatusSeeOther {
  27. return ""
  28. }
  29. return test.RedirectURL(resp)
  30. }
  31. func TestCreateBranch(t *testing.T) {
  32. onGiteaRun(t, testCreateBranches)
  33. }
  34. func testCreateBranches(t *testing.T, giteaURL *url.URL) {
  35. tests := []struct {
  36. OldRefSubURL string
  37. NewBranch string
  38. CreateRelease string
  39. FlashMessage string
  40. ExpectedStatus int
  41. }{
  42. {
  43. OldRefSubURL: "branch/master",
  44. NewBranch: "feature/test1",
  45. ExpectedStatus: http.StatusSeeOther,
  46. FlashMessage: translation.NewLocale("en-US").TrString("repo.branch.create_success", "feature/test1"),
  47. },
  48. {
  49. OldRefSubURL: "branch/master",
  50. NewBranch: "",
  51. ExpectedStatus: http.StatusSeeOther,
  52. FlashMessage: translation.NewLocale("en-US").TrString("form.NewBranchName") + translation.NewLocale("en-US").TrString("form.require_error"),
  53. },
  54. {
  55. OldRefSubURL: "branch/master",
  56. NewBranch: "feature=test1",
  57. ExpectedStatus: http.StatusSeeOther,
  58. FlashMessage: translation.NewLocale("en-US").TrString("repo.branch.create_success", "feature=test1"),
  59. },
  60. {
  61. OldRefSubURL: "branch/master",
  62. NewBranch: strings.Repeat("b", 101),
  63. ExpectedStatus: http.StatusSeeOther,
  64. FlashMessage: translation.NewLocale("en-US").TrString("form.NewBranchName") + translation.NewLocale("en-US").TrString("form.max_size_error", "100"),
  65. },
  66. {
  67. OldRefSubURL: "branch/master",
  68. NewBranch: "master",
  69. ExpectedStatus: http.StatusSeeOther,
  70. FlashMessage: translation.NewLocale("en-US").TrString("repo.branch.branch_already_exists", "master"),
  71. },
  72. {
  73. OldRefSubURL: "branch/master",
  74. NewBranch: "master/test",
  75. ExpectedStatus: http.StatusSeeOther,
  76. FlashMessage: translation.NewLocale("en-US").TrString("repo.branch.branch_name_conflict", "master/test", "master"),
  77. },
  78. {
  79. OldRefSubURL: "commit/acd1d892867872cb47f3993468605b8aa59aa2e0",
  80. NewBranch: "feature/test2",
  81. ExpectedStatus: http.StatusNotFound,
  82. },
  83. {
  84. OldRefSubURL: "commit/65f1bf27bc3bf70f64657658635e66094edbcb4d",
  85. NewBranch: "feature/test3",
  86. ExpectedStatus: http.StatusSeeOther,
  87. FlashMessage: translation.NewLocale("en-US").TrString("repo.branch.create_success", "feature/test3"),
  88. },
  89. {
  90. OldRefSubURL: "branch/master",
  91. NewBranch: "v1.0.0",
  92. CreateRelease: "v1.0.0",
  93. ExpectedStatus: http.StatusSeeOther,
  94. FlashMessage: translation.NewLocale("en-US").TrString("repo.branch.tag_collision", "v1.0.0"),
  95. },
  96. {
  97. OldRefSubURL: "tag/v1.0.0",
  98. NewBranch: "feature/test4",
  99. CreateRelease: "v1.0.1",
  100. ExpectedStatus: http.StatusSeeOther,
  101. FlashMessage: translation.NewLocale("en-US").TrString("repo.branch.create_success", "feature/test4"),
  102. },
  103. }
  104. for _, test := range tests {
  105. session := loginUser(t, "user2")
  106. if test.CreateRelease != "" {
  107. createNewRelease(t, session, "/user2/repo1", test.CreateRelease, test.CreateRelease, false, false)
  108. }
  109. redirectURL := testCreateBranch(t, session, "user2", "repo1", test.OldRefSubURL, test.NewBranch, test.ExpectedStatus)
  110. if test.ExpectedStatus == http.StatusSeeOther {
  111. req := NewRequest(t, "GET", redirectURL)
  112. resp := session.MakeRequest(t, req, http.StatusOK)
  113. htmlDoc := NewHTMLParser(t, resp.Body)
  114. assert.Contains(t,
  115. strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()),
  116. test.FlashMessage,
  117. )
  118. }
  119. }
  120. }
  121. func TestCreateBranchInvalidCSRF(t *testing.T) {
  122. defer tests.PrepareTestEnv(t)()
  123. session := loginUser(t, "user2")
  124. req := NewRequestWithValues(t, "POST", "user2/repo1/branches/_new/branch/master", map[string]string{
  125. "_csrf": "fake_csrf",
  126. "new_branch_name": "test",
  127. })
  128. resp := session.MakeRequest(t, req, http.StatusBadRequest)
  129. assert.Contains(t, resp.Body.String(), "Invalid CSRF token")
  130. }
  131. func prepareRecentlyPushedBranchTest(t *testing.T, headSession *TestSession, baseRepo, headRepo *repo_model.Repository) {
  132. refSubURL := "branch/" + headRepo.DefaultBranch
  133. baseRepoPath := baseRepo.OwnerName + "/" + baseRepo.Name
  134. headRepoPath := headRepo.OwnerName + "/" + headRepo.Name
  135. // Case 1: Normal branch changeset to display pushed message
  136. // create branch with no new commit
  137. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, refSubURL, "no-commit", http.StatusSeeOther)
  138. // create branch with commit
  139. testAPINewFile(t, headSession, headRepo.OwnerName, headRepo.Name, "new-commit", fmt.Sprintf("new-file-%s.txt", headRepo.Name), "new-commit")
  140. // create a branch then delete it
  141. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "deleted-branch", http.StatusSeeOther)
  142. testUIDeleteBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "deleted-branch")
  143. // only `new-commit` branch has commits ahead the base branch
  144. checkRecentlyPushedNewBranches(t, headSession, headRepoPath, []string{"new-commit"})
  145. if baseRepo.RepoPath() != headRepo.RepoPath() {
  146. checkRecentlyPushedNewBranches(t, headSession, baseRepoPath, []string{fmt.Sprintf("%v:new-commit", headRepo.FullName())})
  147. }
  148. // Case 2: Create PR so that `new-commit` branch will not show
  149. testCreatePullToDefaultBranch(t, headSession, baseRepo, headRepo, "new-commit", "merge new-commit to default branch")
  150. // No push message show because of active PR
  151. checkRecentlyPushedNewBranches(t, headSession, headRepoPath, []string{})
  152. if baseRepo.RepoPath() != headRepo.RepoPath() {
  153. checkRecentlyPushedNewBranches(t, headSession, baseRepoPath, []string{})
  154. }
  155. }
  156. func prepareRecentlyPushedBranchSpecialTest(t *testing.T, session *TestSession, baseRepo, headRepo *repo_model.Repository) {
  157. refSubURL := "branch/" + headRepo.DefaultBranch
  158. baseRepoPath := baseRepo.OwnerName + "/" + baseRepo.Name
  159. headRepoPath := headRepo.OwnerName + "/" + headRepo.Name
  160. // create branch with no new commit
  161. testCreateBranch(t, session, headRepo.OwnerName, headRepo.Name, refSubURL, "no-commit-special", http.StatusSeeOther)
  162. // update base (default) branch before head branch is updated
  163. testAPINewFile(t, session, baseRepo.OwnerName, baseRepo.Name, baseRepo.DefaultBranch, fmt.Sprintf("new-file-special-%s.txt", headRepo.Name), "new-commit")
  164. // Though we have new `no-commit` branch, but the headBranch is not newer or commits ahead baseBranch. No message show.
  165. checkRecentlyPushedNewBranches(t, session, headRepoPath, []string{})
  166. if baseRepo.RepoPath() != headRepo.RepoPath() {
  167. checkRecentlyPushedNewBranches(t, session, baseRepoPath, []string{})
  168. }
  169. }
  170. func testCreatePullToDefaultBranch(t *testing.T, session *TestSession, baseRepo, headRepo *repo_model.Repository, headBranch, title string) string {
  171. srcRef := headBranch
  172. if baseRepo.ID != headRepo.ID {
  173. srcRef = fmt.Sprintf("%s/%s:%s", headRepo.OwnerName, headRepo.Name, headBranch)
  174. }
  175. resp := testPullCreate(t, session, baseRepo.OwnerName, baseRepo.Name, false, baseRepo.DefaultBranch, srcRef, title)
  176. elem := strings.Split(test.RedirectURL(resp), "/")
  177. // return pull request ID
  178. return elem[4]
  179. }
  180. func prepareRepoPR(t *testing.T, baseSession, headSession *TestSession, baseRepo, headRepo *repo_model.Repository) {
  181. refSubURL := "branch/" + headRepo.DefaultBranch
  182. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, refSubURL, "new-commit", http.StatusSeeOther)
  183. // create opening PR
  184. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "opening-pr", http.StatusSeeOther)
  185. testCreatePullToDefaultBranch(t, baseSession, baseRepo, headRepo, "opening-pr", "opening pr")
  186. // create closed PR
  187. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "closed-pr", http.StatusSeeOther)
  188. prID := testCreatePullToDefaultBranch(t, baseSession, baseRepo, headRepo, "closed-pr", "closed pr")
  189. testIssueClose(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID)
  190. // create closed PR with deleted branch
  191. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "closed-pr-deleted", http.StatusSeeOther)
  192. prID = testCreatePullToDefaultBranch(t, baseSession, baseRepo, headRepo, "closed-pr-deleted", "closed pr with deleted branch")
  193. testIssueClose(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID)
  194. testUIDeleteBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "closed-pr-deleted")
  195. // create merged PR
  196. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "merged-pr", http.StatusSeeOther)
  197. prID = testCreatePullToDefaultBranch(t, baseSession, baseRepo, headRepo, "merged-pr", "merged pr")
  198. testAPINewFile(t, headSession, headRepo.OwnerName, headRepo.Name, "merged-pr", fmt.Sprintf("new-commit-%s.txt", headRepo.Name), "new-commit")
  199. testPullMerge(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID, repo_model.MergeStyleRebaseMerge, false)
  200. // create merged PR with deleted branch
  201. testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "merged-pr-deleted", http.StatusSeeOther)
  202. prID = testCreatePullToDefaultBranch(t, baseSession, baseRepo, headRepo, "merged-pr-deleted", "merged pr with deleted branch")
  203. testAPINewFile(t, headSession, headRepo.OwnerName, headRepo.Name, "merged-pr-deleted", fmt.Sprintf("new-commit-%s-2.txt", headRepo.Name), "new-commit")
  204. testPullMerge(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID, repo_model.MergeStyleRebaseMerge, true)
  205. }
  206. func checkRecentlyPushedNewBranches(t *testing.T, session *TestSession, repoPath string, expected []string) {
  207. branches := make([]string, 0, 2)
  208. req := NewRequest(t, "GET", repoPath)
  209. resp := session.MakeRequest(t, req, http.StatusOK)
  210. doc := NewHTMLParser(t, resp.Body)
  211. doc.doc.Find(".ui.positive.message div a").Each(func(index int, branch *goquery.Selection) {
  212. branches = append(branches, branch.Text())
  213. })
  214. assert.Equal(t, expected, branches)
  215. }
  216. func TestRecentlyPushedNewBranches(t *testing.T) {
  217. onGiteaRun(t, func(t *testing.T, u *url.URL) {
  218. user12Session := loginUser(t, "user12")
  219. // Same reposioty check
  220. repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
  221. prepareRepoPR(t, user12Session, user12Session, repo10, repo10)
  222. prepareRecentlyPushedBranchTest(t, user12Session, repo10, repo10)
  223. prepareRecentlyPushedBranchSpecialTest(t, user12Session, repo10, repo10)
  224. // create a fork repo in public org
  225. testRepoFork(t, user12Session, repo10.OwnerName, repo10.Name, "org25", "org25_fork_repo10", repo10.DefaultBranch)
  226. orgPublicForkRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 25, Name: "org25_fork_repo10"})
  227. prepareRepoPR(t, user12Session, user12Session, repo10, orgPublicForkRepo)
  228. prepareRecentlyPushedBranchTest(t, user12Session, repo10, orgPublicForkRepo)
  229. prepareRecentlyPushedBranchSpecialTest(t, user12Session, repo10, orgPublicForkRepo)
  230. })
  231. }