diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2024-04-09 11:43:17 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-09 03:43:17 +0000 |
commit | 263a716cb52037f3e7e51f014f6c8cdfad6ae03d (patch) | |
tree | 2ca921707de7f1d35bacefe0f06a9ea0aa676f32 /routers/private | |
parent | 72dc75e594fb5227abfa1cb74cb652cc33bacc93 (diff) | |
download | gitea-263a716cb52037f3e7e51f014f6c8cdfad6ae03d.tar.gz gitea-263a716cb52037f3e7e51f014f6c8cdfad6ae03d.zip |
Performance optimization for git push (#30104)
Agit returned result should be from `ProcReceive` hook but not
`PostReceive` hook. Then for all non-agit pull requests, it will not
check the pull requests for every pushing `refs/pull/%d/head`.
Diffstat (limited to 'routers/private')
-rw-r--r-- | routers/private/hook_post_receive.go | 85 |
1 files changed, 44 insertions, 41 deletions
diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 101ae92302..769a68970d 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -6,11 +6,12 @@ package private import ( "fmt" "net/http" - "strconv" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" @@ -159,8 +160,10 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { } } + isPrivate := opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate) + isTemplate := opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate) // Handle Push Options - if len(opts.GitPushOptions) > 0 { + if isPrivate.Has() || isTemplate.Has() { // load the repository if repo == nil { repo = loadRepository(ctx, ownerName, repoName) @@ -171,13 +174,49 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { wasEmpty = repo.IsEmpty } - repo.IsPrivate = opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate, repo.IsPrivate) - repo.IsTemplate = opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate, repo.IsTemplate) - if err := repo_model.UpdateRepositoryCols(ctx, repo, "is_private", "is_template"); err != nil { + pusher, err := user_model.GetUserByID(ctx, opts.UserID) + if err != nil { log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err) ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err), }) + return + } + perm, err := access_model.GetUserRepoPermission(ctx, repo, pusher) + if err != nil { + log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err) + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ + Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err), + }) + return + } + if !perm.IsOwner() && !perm.IsAdmin() { + ctx.JSON(http.StatusNotFound, private.HookPostReceiveResult{ + Err: "Permissions denied", + }) + return + } + + cols := make([]string, 0, len(opts.GitPushOptions)) + + if isPrivate.Has() { + repo.IsPrivate = isPrivate.Value() + cols = append(cols, "is_private") + } + + if isTemplate.Has() { + repo.IsTemplate = isTemplate.Value() + cols = append(cols, "is_template") + } + + if len(cols) > 0 { + if err := repo_model.UpdateRepositoryCols(ctx, repo, cols...); err != nil { + log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err) + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ + Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err), + }) + return + } } } @@ -192,42 +231,6 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { refFullName := opts.RefFullNames[i] newCommitID := opts.NewCommitIDs[i] - // post update for agit pull request - // FIXME: use pr.Flow to test whether it's an Agit PR or a GH PR - if git.DefaultFeatures.SupportProcReceive && refFullName.IsPull() { - if repo == nil { - repo = loadRepository(ctx, ownerName, repoName) - if ctx.Written() { - return - } - } - - pullIndex, _ := strconv.ParseInt(refFullName.PullName(), 10, 64) - if pullIndex <= 0 { - continue - } - - pr, err := issues_model.GetPullRequestByIndex(ctx, repo.ID, pullIndex) - if err != nil && !issues_model.IsErrPullRequestNotExist(err) { - log.Error("Failed to get PR by index %v Error: %v", pullIndex, err) - ctx.JSON(http.StatusInternalServerError, private.Response{ - Err: fmt.Sprintf("Failed to get PR by index %v Error: %v", pullIndex, err), - }) - return - } - if pr == nil { - continue - } - - results = append(results, private.HookPostReceiveBranchResult{ - Message: setting.Git.PullRequestPushMessage && repo.AllowsPulls(ctx), - Create: false, - Branch: "", - URL: fmt.Sprintf("%s/pulls/%d", repo.HTMLURL(), pr.Index), - }) - continue - } - // If we've pushed a branch (and not deleted it) if !git.IsEmptyCommitID(newCommitID) && refFullName.IsBranch() { // First ensure we have the repository loaded, we're allowed pulls requests and we can get the base repo |