mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 00:20:25 +08:00 
			
		
		
		
	Use for a repo action one database transaction (#19576)
... more context (part of #9307)
This commit is contained in:
		@@ -14,6 +14,7 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	"code.gitea.io/gitea/models/unit"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
@@ -59,70 +60,72 @@ func AddToTaskQueue(pr *models.PullRequest) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CheckPullMergable check if the pull mergable based on all conditions (branch protection, merge options, ...)
 | 
			
		||||
func CheckPullMergable(ctx context.Context, doer *user_model.User, perm *models.Permission, pr *models.PullRequest, manuallMerge, force bool) error {
 | 
			
		||||
	if pr.HasMerged {
 | 
			
		||||
		return ErrHasMerged
 | 
			
		||||
	}
 | 
			
		||||
func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *models.Permission, pr *models.PullRequest, manuallMerge, force bool) error {
 | 
			
		||||
	return db.WithTx(func(ctx context.Context) error {
 | 
			
		||||
		if pr.HasMerged {
 | 
			
		||||
			return ErrHasMerged
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if err := pr.LoadIssue(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	} else if pr.Issue.IsClosed {
 | 
			
		||||
		return ErrIsClosed
 | 
			
		||||
	}
 | 
			
		||||
		if err := pr.LoadIssueCtx(ctx); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if pr.Issue.IsClosed {
 | 
			
		||||
			return ErrIsClosed
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if allowedMerge, err := IsUserAllowedToMerge(pr, *perm, doer); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	} else if !allowedMerge {
 | 
			
		||||
		return ErrUserNotAllowedToMerge
 | 
			
		||||
	}
 | 
			
		||||
		if allowedMerge, err := IsUserAllowedToMerge(ctx, pr, *perm, doer); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if !allowedMerge {
 | 
			
		||||
			return ErrUserNotAllowedToMerge
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if manuallMerge {
 | 
			
		||||
		// don't check rules to "auto merge", doer is going to mark this pull as merged manually
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
		if manuallMerge {
 | 
			
		||||
			// don't check rules to "auto merge", doer is going to mark this pull as merged manually
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if pr.IsWorkInProgress() {
 | 
			
		||||
		return ErrIsWorkInProgress
 | 
			
		||||
	}
 | 
			
		||||
		if pr.IsWorkInProgress() {
 | 
			
		||||
			return ErrIsWorkInProgress
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if !pr.CanAutoMerge() {
 | 
			
		||||
		return ErrNotMergableState
 | 
			
		||||
	}
 | 
			
		||||
		if !pr.CanAutoMerge() {
 | 
			
		||||
			return ErrNotMergableState
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if pr.IsChecking() {
 | 
			
		||||
		return ErrIsChecking
 | 
			
		||||
	}
 | 
			
		||||
		if pr.IsChecking() {
 | 
			
		||||
			return ErrIsChecking
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if err := CheckPullBranchProtections(ctx, pr, false); err != nil {
 | 
			
		||||
		if models.IsErrDisallowedToMerge(err) {
 | 
			
		||||
			if force {
 | 
			
		||||
				if isRepoAdmin, err2 := models.IsUserRepoAdmin(pr.BaseRepo, doer); err2 != nil {
 | 
			
		||||
					return err2
 | 
			
		||||
				} else if !isRepoAdmin {
 | 
			
		||||
					return err
 | 
			
		||||
		if err := CheckPullBranchProtections(ctx, pr, false); err != nil {
 | 
			
		||||
			if models.IsErrDisallowedToMerge(err) {
 | 
			
		||||
				if force {
 | 
			
		||||
					if isRepoAdmin, err2 := models.IsUserRepoAdminCtx(ctx, pr.BaseRepo, doer); err2 != nil {
 | 
			
		||||
						return err2
 | 
			
		||||
					} else if !isRepoAdmin {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, err := isSignedIfRequired(ctx, pr, doer); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := isSignedIfRequired(ctx, pr, doer); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
		if noDeps, err := models.IssueNoDependenciesLeft(ctx, pr.Issue); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if !noDeps {
 | 
			
		||||
			return ErrDependenciesLeft
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if noDeps, err := models.IssueNoDependenciesLeft(pr.Issue); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	} else if !noDeps {
 | 
			
		||||
		return ErrDependenciesLeft
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
		return nil
 | 
			
		||||
	}, stdCtx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// isSignedIfRequired check if merge will be signed if required
 | 
			
		||||
func isSignedIfRequired(ctx context.Context, pr *models.PullRequest, doer *user_model.User) (bool, error) {
 | 
			
		||||
	if err := pr.LoadProtectedBranch(); err != nil {
 | 
			
		||||
	if err := pr.LoadProtectedBranchCtx(ctx); err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -266,7 +269,7 @@ func manuallyMerged(ctx context.Context, pr *models.PullRequest) bool {
 | 
			
		||||
		pr.Merger = merger
 | 
			
		||||
		pr.MergerID = merger.ID
 | 
			
		||||
 | 
			
		||||
		if merged, err := pr.SetMerged(); err != nil {
 | 
			
		||||
		if merged, err := pr.SetMerged(ctx); err != nil {
 | 
			
		||||
			log.Error("PullRequest[%d].setMerged : %v", pr.ID, err)
 | 
			
		||||
			return false
 | 
			
		||||
		} else if !merged {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user