You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

setting_protected_branch.go 9.0 kB

2 years ago
Improve listing performance by using go-git (#6478) * Use go-git for tree reading and commit info lookup. Signed-off-by: Filip Navara <navara@emclient.com> * Use TreeEntry.IsRegular() instead of ObjectType that was removed. Signed-off-by: Filip Navara <navara@emclient.com> * Use the treePath to optimize commit info search. Signed-off-by: Filip Navara <navara@emclient.com> * Extract the latest commit at treePath along with the other commits. Signed-off-by: Filip Navara <navara@emclient.com> * Fix listing commit info for a directory that was created in one commit and never modified after. Signed-off-by: Filip Navara <navara@emclient.com> * Avoid nearly all external 'git' invocations when doing directory listing (.editorconfig code path is still hit). Signed-off-by: Filip Navara <navara@emclient.com> * Use go-git for reading blobs. Signed-off-by: Filip Navara <navara@emclient.com> * Make SHA1 type alias for plumbing.Hash in go-git. Signed-off-by: Filip Navara <navara@emclient.com> * Make Signature type alias for object.Signature in go-git. Signed-off-by: Filip Navara <navara@emclient.com> * Fix GetCommitsInfo for repository with only one commit. Signed-off-by: Filip Navara <navara@emclient.com> * Fix PGP signature verification. Signed-off-by: Filip Navara <navara@emclient.com> * Fix issues with walking commit graph across merges. Signed-off-by: Filip Navara <navara@emclient.com> * Fix typo in condition. Signed-off-by: Filip Navara <navara@emclient.com> * Speed up loading branch list by keeping the repository reference (and thus all the loaded packfile indexes). Signed-off-by: Filip Navara <navara@emclient.com> * Fix lising submodules. Signed-off-by: Filip Navara <navara@emclient.com> * Fix build Signed-off-by: Filip Navara <navara@emclient.com> * Add back commit cache because of name-rev Signed-off-by: Filip Navara <navara@emclient.com> * Fix tests Signed-off-by: Filip Navara <navara@emclient.com> * Fix code style * Fix spelling * Address PR feedback Signed-off-by: Filip Navara <navara@emclient.com> * Update vendor module list Signed-off-by: Filip Navara <navara@emclient.com> * Fix getting trees by commit id Signed-off-by: Filip Navara <navara@emclient.com> * Fix remaining unit test failures * Fix GetTreeBySHA * Avoid running `git name-rev` if not necessary Signed-off-by: Filip Navara <navara@emclient.com> * Move Branch code to git module * Clean up GPG signature verification and fix it for tagged commits * Address PR feedback (import formatting, copyright headers) * Make blob lookup by SHA working * Update tests to use public API * Allow getting content from any type of object through the blob interface * Change test to actually expect the object content that is in the GIT repository * Change one more test to actually expect the object content that is in the GIT repository * Add comments
6 years ago
Improve listing performance by using go-git (#6478) * Use go-git for tree reading and commit info lookup. Signed-off-by: Filip Navara <navara@emclient.com> * Use TreeEntry.IsRegular() instead of ObjectType that was removed. Signed-off-by: Filip Navara <navara@emclient.com> * Use the treePath to optimize commit info search. Signed-off-by: Filip Navara <navara@emclient.com> * Extract the latest commit at treePath along with the other commits. Signed-off-by: Filip Navara <navara@emclient.com> * Fix listing commit info for a directory that was created in one commit and never modified after. Signed-off-by: Filip Navara <navara@emclient.com> * Avoid nearly all external 'git' invocations when doing directory listing (.editorconfig code path is still hit). Signed-off-by: Filip Navara <navara@emclient.com> * Use go-git for reading blobs. Signed-off-by: Filip Navara <navara@emclient.com> * Make SHA1 type alias for plumbing.Hash in go-git. Signed-off-by: Filip Navara <navara@emclient.com> * Make Signature type alias for object.Signature in go-git. Signed-off-by: Filip Navara <navara@emclient.com> * Fix GetCommitsInfo for repository with only one commit. Signed-off-by: Filip Navara <navara@emclient.com> * Fix PGP signature verification. Signed-off-by: Filip Navara <navara@emclient.com> * Fix issues with walking commit graph across merges. Signed-off-by: Filip Navara <navara@emclient.com> * Fix typo in condition. Signed-off-by: Filip Navara <navara@emclient.com> * Speed up loading branch list by keeping the repository reference (and thus all the loaded packfile indexes). Signed-off-by: Filip Navara <navara@emclient.com> * Fix lising submodules. Signed-off-by: Filip Navara <navara@emclient.com> * Fix build Signed-off-by: Filip Navara <navara@emclient.com> * Add back commit cache because of name-rev Signed-off-by: Filip Navara <navara@emclient.com> * Fix tests Signed-off-by: Filip Navara <navara@emclient.com> * Fix code style * Fix spelling * Address PR feedback Signed-off-by: Filip Navara <navara@emclient.com> * Update vendor module list Signed-off-by: Filip Navara <navara@emclient.com> * Fix getting trees by commit id Signed-off-by: Filip Navara <navara@emclient.com> * Fix remaining unit test failures * Fix GetTreeBySHA * Avoid running `git name-rev` if not necessary Signed-off-by: Filip Navara <navara@emclient.com> * Move Branch code to git module * Clean up GPG signature verification and fix it for tagged commits * Address PR feedback (import formatting, copyright headers) * Make blob lookup by SHA working * Update tests to use public API * Allow getting content from any type of object through the blob interface * Change test to actually expect the object content that is in the GIT repository * Change one more test to actually expect the object content that is in the GIT repository * Add comments
6 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "code.gitea.io/gitea/modules/util"
  7. "fmt"
  8. "strings"
  9. "time"
  10. "code.gitea.io/gitea/models"
  11. "code.gitea.io/gitea/modules/auth"
  12. "code.gitea.io/gitea/modules/base"
  13. "code.gitea.io/gitea/modules/context"
  14. "code.gitea.io/gitea/modules/git"
  15. "code.gitea.io/gitea/modules/log"
  16. "code.gitea.io/gitea/modules/setting"
  17. )
  18. // ProtectedBranch render the page to protect the repository
  19. func ProtectedBranch(ctx *context.Context) {
  20. ctx.Data["Title"] = ctx.Tr("repo.settings")
  21. ctx.Data["PageIsSettingsBranches"] = true
  22. protectedBranches, err := ctx.Repo.Repository.GetProtectedBranches()
  23. if err != nil {
  24. ctx.ServerError("GetProtectedBranches", err)
  25. return
  26. }
  27. ctx.Data["ProtectedBranches"] = protectedBranches
  28. branches := ctx.Data["Branches"].([]string)
  29. leftBranches := make([]string, 0, len(branches)-len(protectedBranches))
  30. for _, b := range branches {
  31. var protected bool
  32. for _, pb := range protectedBranches {
  33. if b == pb.BranchName {
  34. protected = true
  35. break
  36. }
  37. }
  38. if !protected {
  39. leftBranches = append(leftBranches, b)
  40. }
  41. }
  42. ctx.Data["LeftBranches"] = leftBranches
  43. ctx.HTML(200, tplBranches)
  44. }
  45. // ProtectedBranchPost response for protect for a branch of a repository
  46. func ProtectedBranchPost(ctx *context.Context) {
  47. ctx.Data["Title"] = ctx.Tr("repo.settings")
  48. ctx.Data["PageIsSettingsBranches"] = true
  49. repo := ctx.Repo.Repository
  50. switch ctx.Query("action") {
  51. case "default_branch":
  52. if ctx.HasError() {
  53. ctx.HTML(200, tplBranches)
  54. return
  55. }
  56. branch := ctx.Query("branch")
  57. if !ctx.Repo.GitRepo.IsBranchExist(branch) {
  58. ctx.Status(404)
  59. return
  60. } else if repo.DefaultBranch != branch {
  61. repo.DefaultBranch = branch
  62. if err := ctx.Repo.GitRepo.SetDefaultBranch(branch); err != nil {
  63. if !git.IsErrUnsupportedVersion(err) {
  64. ctx.ServerError("SetDefaultBranch", err)
  65. return
  66. }
  67. }
  68. if err := repo.UpdateDefaultBranch(); err != nil {
  69. ctx.ServerError("SetDefaultBranch", err)
  70. return
  71. }
  72. }
  73. log.Trace("Repository basic settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name)
  74. ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
  75. ctx.Redirect(setting.AppSubURL + ctx.Req.URL.Path)
  76. default:
  77. ctx.NotFound("", nil)
  78. }
  79. }
  80. // SettingsProtectedBranch renders the protected branch setting page
  81. func SettingsProtectedBranch(c *context.Context) {
  82. branch := c.Params("*")
  83. if !c.Repo.GitRepo.IsBranchExist(branch) {
  84. c.NotFound("IsBranchExist", nil)
  85. return
  86. }
  87. c.Data["Title"] = c.Tr("repo.settings.protected_branch") + " - " + branch
  88. c.Data["PageIsSettingsBranches"] = true
  89. protectBranch, err := models.GetProtectedBranchBy(c.Repo.Repository.ID, branch)
  90. if err != nil {
  91. if !git.IsErrBranchNotExist(err) {
  92. c.ServerError("GetProtectBranchOfRepoByName", err)
  93. return
  94. }
  95. }
  96. if protectBranch == nil {
  97. // No options found, create defaults.
  98. protectBranch = &models.ProtectedBranch{
  99. BranchName: branch,
  100. }
  101. }
  102. users, err := c.Repo.Repository.GetReaders()
  103. if err != nil {
  104. c.ServerError("Repo.Repository.GetReaders", err)
  105. return
  106. }
  107. c.Data["Users"] = users
  108. c.Data["whitelist_users"] = strings.Join(base.Int64sToStrings(protectBranch.WhitelistUserIDs), ",")
  109. c.Data["merge_whitelist_users"] = strings.Join(base.Int64sToStrings(protectBranch.MergeWhitelistUserIDs), ",")
  110. c.Data["approvals_whitelist_users"] = strings.Join(base.Int64sToStrings(protectBranch.ApprovalsWhitelistUserIDs), ",")
  111. contexts, _ := models.FindRepoRecentCommitStatusContexts(c.Repo.Repository.ID, 7*24*time.Hour) // Find last week status check contexts
  112. for _, context := range protectBranch.StatusCheckContexts {
  113. var found bool
  114. for _, ctx := range contexts {
  115. if ctx == context {
  116. found = true
  117. break
  118. }
  119. }
  120. if !found {
  121. contexts = append(contexts, context)
  122. }
  123. }
  124. c.Data["branch_status_check_contexts"] = contexts
  125. c.Data["is_context_required"] = func(context string) bool {
  126. for _, c := range protectBranch.StatusCheckContexts {
  127. if c == context {
  128. return true
  129. }
  130. }
  131. return false
  132. }
  133. if c.Repo.Owner.IsOrganization() {
  134. teams, err := c.Repo.Owner.TeamsWithAccessToRepo(c.Repo.Repository.ID, models.AccessModeRead)
  135. if err != nil {
  136. c.ServerError("Repo.Owner.TeamsWithAccessToRepo", err)
  137. return
  138. }
  139. c.Data["Teams"] = teams
  140. c.Data["whitelist_teams"] = strings.Join(base.Int64sToStrings(protectBranch.WhitelistTeamIDs), ",")
  141. c.Data["merge_whitelist_teams"] = strings.Join(base.Int64sToStrings(protectBranch.MergeWhitelistTeamIDs), ",")
  142. c.Data["approvals_whitelist_teams"] = strings.Join(base.Int64sToStrings(protectBranch.ApprovalsWhitelistTeamIDs), ",")
  143. }
  144. c.Data["Branch"] = protectBranch
  145. c.HTML(200, tplProtectedBranch)
  146. }
  147. // SettingsProtectedBranchPost updates the protected branch settings
  148. func SettingsProtectedBranchPost(ctx *context.Context, f auth.ProtectBranchForm) {
  149. branch := ctx.Params("*")
  150. if !ctx.Repo.GitRepo.IsBranchExist(branch) {
  151. ctx.NotFound("IsBranchExist", nil)
  152. return
  153. }
  154. protectBranch, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, branch)
  155. if err != nil {
  156. if !git.IsErrBranchNotExist(err) {
  157. ctx.ServerError("GetProtectBranchOfRepoByName", err)
  158. return
  159. }
  160. }
  161. if f.Protected {
  162. if protectBranch == nil {
  163. // No options found, create defaults.
  164. protectBranch = &models.ProtectedBranch{
  165. RepoID: ctx.Repo.Repository.ID,
  166. BranchName: branch,
  167. }
  168. }
  169. if f.RequiredApprovals < 0 {
  170. ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_required_approvals_min"))
  171. ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
  172. }
  173. var whitelistUsers, whitelistTeams, mergeWhitelistUsers, mergeWhitelistTeams, approvalsWhitelistUsers, approvalsWhitelistTeams []int64
  174. switch f.EnablePush {
  175. case "all":
  176. protectBranch.CanPush = true
  177. protectBranch.EnableWhitelist = false
  178. protectBranch.WhitelistDeployKeys = false
  179. case "whitelist":
  180. protectBranch.CanPush = true
  181. protectBranch.EnableWhitelist = true
  182. protectBranch.WhitelistDeployKeys = f.WhitelistDeployKeys
  183. if strings.TrimSpace(f.WhitelistUsers) != "" {
  184. whitelistUsers, _ = base.StringsToInt64s(strings.Split(f.WhitelistUsers, ","))
  185. }
  186. if strings.TrimSpace(f.WhitelistTeams) != "" {
  187. whitelistTeams, _ = base.StringsToInt64s(strings.Split(f.WhitelistTeams, ","))
  188. }
  189. default:
  190. protectBranch.CanPush = false
  191. protectBranch.EnableWhitelist = false
  192. protectBranch.WhitelistDeployKeys = false
  193. }
  194. protectBranch.EnableMergeWhitelist = f.EnableMergeWhitelist
  195. if f.EnableMergeWhitelist {
  196. if strings.TrimSpace(f.MergeWhitelistUsers) != "" {
  197. mergeWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistUsers, ","))
  198. }
  199. if strings.TrimSpace(f.MergeWhitelistTeams) != "" {
  200. mergeWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistTeams, ","))
  201. }
  202. }
  203. protectBranch.EnableStatusCheck = f.EnableStatusCheck
  204. if f.EnableStatusCheck {
  205. protectBranch.StatusCheckContexts = f.StatusCheckContexts
  206. } else {
  207. protectBranch.StatusCheckContexts = nil
  208. }
  209. protectBranch.RequiredApprovals = f.RequiredApprovals
  210. protectBranch.EnableApprovalsWhitelist = f.EnableApprovalsWhitelist
  211. if f.EnableApprovalsWhitelist {
  212. if strings.TrimSpace(f.ApprovalsWhitelistUsers) != "" {
  213. approvalsWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistUsers, ","))
  214. }
  215. if strings.TrimSpace(f.ApprovalsWhitelistTeams) != "" {
  216. approvalsWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistTeams, ","))
  217. }
  218. }
  219. protectBranch.BlockOnRejectedReviews = f.BlockOnRejectedReviews
  220. protectBranch.DismissStaleApprovals = f.DismissStaleApprovals
  221. protectBranch.RequireSignedCommits = f.RequireSignedCommits
  222. protectBranch.ProtectedFilePatterns = f.ProtectedFilePatterns
  223. protectBranch.BlockOnOutdatedBranch = f.BlockOnOutdatedBranch
  224. err = models.UpdateProtectBranch(ctx.Repo.Repository, protectBranch, models.WhitelistOptions{
  225. UserIDs: whitelistUsers,
  226. TeamIDs: whitelistTeams,
  227. MergeUserIDs: mergeWhitelistUsers,
  228. MergeTeamIDs: mergeWhitelistTeams,
  229. ApprovalsUserIDs: approvalsWhitelistUsers,
  230. ApprovalsTeamIDs: approvalsWhitelistTeams,
  231. })
  232. if err != nil {
  233. ctx.ServerError("UpdateProtectBranch", err)
  234. return
  235. }
  236. ctx.Flash.Success(ctx.Tr("repo.settings.update_protect_branch_success", branch))
  237. ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
  238. } else {
  239. if protectBranch != nil {
  240. if err := ctx.Repo.Repository.DeleteProtectedBranch(protectBranch.ID); err != nil {
  241. ctx.ServerError("DeleteProtectedBranch", err)
  242. return
  243. }
  244. }
  245. ctx.Flash.Success(ctx.Tr("repo.settings.remove_protected_branch_success", branch))
  246. ctx.Redirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink))
  247. }
  248. }