summaryrefslogtreecommitdiffstats
path: root/routers/private
diff options
context:
space:
mode:
authorJason Song <i@wolfogre.com>2024-03-06 09:47:52 +0100
committeroliverpool <git@olivier.pfad.fr>2024-03-18 17:38:01 +0100
commit286d09203f3b77a2dc26c28b278a16953e5ee523 (patch)
treee977dcecf1e9e650cc048569661f0b3ef15ae4b1 /routers/private
parentMerge pull request '[Windows] prevent ? in testdata path' (#2668) from oliver... (diff)
downloadforgejo-286d09203f3b77a2dc26c28b278a16953e5ee523.tar.xz
forgejo-286d09203f3b77a2dc26c28b278a16953e5ee523.zip
Sync branches to DB immediately when handle git hook calling (gitea#29493)
Unlike other async processing in the queue, we should sync branches to the DB immediately when handling git hook calling. If it fails, users can see the error message in the output of the git command. It can avoid potential inconsistency issues, and help #29494. --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'routers/private')
-rw-r--r--routers/private/hook_post_receive.go66
1 files changed, 65 insertions, 1 deletions
diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go
index f4c698d3ea..c34c0013d5 100644
--- a/routers/private/hook_post_receive.go
+++ b/routers/private/hook_post_receive.go
@@ -8,9 +8,11 @@ import (
"net/http"
"strconv"
+ git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
repo_module "code.gitea.io/gitea/modules/repository"
@@ -27,6 +29,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
// We don't rely on RepoAssignment here because:
// a) we don't need the git repo in this function
+ // OUT OF DATE: we do need the git repo to sync the branch to the db now.
// b) our update function will likely change the repository in the db so we will need to refresh it
// c) we don't always need the repo
@@ -34,7 +37,11 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
repoName := ctx.Params(":repo")
// defer getting the repository at this point - as we should only retrieve it if we're going to call update
- var repo *repo_model.Repository
+ var (
+ repo *repo_model.Repository
+ gitRepo *git.Repository
+ )
+ defer gitRepo.Close() // it's safe to call Close on a nil pointer
updates := make([]*repo_module.PushUpdateOptions, 0, len(opts.OldCommitIDs))
wasEmpty := false
@@ -87,6 +94,63 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
})
return
}
+
+ branchesToSync := make([]*repo_module.PushUpdateOptions, 0, len(updates))
+ for _, update := range updates {
+ if !update.RefFullName.IsBranch() {
+ continue
+ }
+ if repo == nil {
+ repo = loadRepository(ctx, ownerName, repoName)
+ if ctx.Written() {
+ return
+ }
+ wasEmpty = repo.IsEmpty
+ }
+
+ if update.IsDelRef() {
+ if err := git_model.AddDeletedBranch(ctx, repo.ID, update.RefFullName.BranchName(), update.PusherID); err != nil {
+ log.Error("Failed to add deleted branch: %s/%s Error: %v", ownerName, repoName, err)
+ ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
+ Err: fmt.Sprintf("Failed to add deleted branch: %s/%s Error: %v", ownerName, repoName, err),
+ })
+ return
+ }
+ } else {
+ branchesToSync = append(branchesToSync, update)
+ }
+ }
+ if len(branchesToSync) > 0 {
+ if gitRepo == nil {
+ var err error
+ gitRepo, err = gitrepo.OpenRepository(ctx, repo)
+ if err != nil {
+ log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err)
+ ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
+ Err: fmt.Sprintf("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err),
+ })
+ return
+ }
+ }
+
+ var (
+ branchNames = make([]string, 0, len(branchesToSync))
+ commitIDs = make([]string, 0, len(branchesToSync))
+ )
+ for _, update := range branchesToSync {
+ branchNames = append(branchNames, update.RefFullName.BranchName())
+ commitIDs = append(commitIDs, update.NewCommitID)
+ }
+
+ if err := repo_service.SyncBranchesToDB(ctx, repo.ID, opts.UserID, branchNames, commitIDs, func(commitID string) (*git.Commit, error) {
+ return gitRepo.GetCommit(commitID)
+ }); err != nil {
+ ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
+ Err: fmt.Sprintf("Failed to sync branch to DB in repository: %s/%s Error: %v", ownerName, repoName, err),
+ })
+ return
+ }
+ }
}
// Handle Push Options