feat: vendor gitea 1.16.2
This commit is contained in:
@@ -14,7 +14,7 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
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/globallock"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/repository"
|
||||
@@ -34,17 +34,21 @@ func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.
|
||||
}
|
||||
defer releaser()
|
||||
|
||||
diffCount, err := GetDiverging(ctx, pr)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if diffCount.Behind == 0 {
|
||||
return fmt.Errorf("HeadBranch of PR %d is up to date", pr.Index)
|
||||
}
|
||||
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
log.Error("unable to load BaseRepo for %-v during update-by-merge: %v", pr, err)
|
||||
return fmt.Errorf("unable to load BaseRepo for PR[%d] during update-by-merge: %w", pr.ID, err)
|
||||
}
|
||||
|
||||
// TODO: FakePR: if the PR is a fake PR (for example: from Merge Upstream), then no need to check diverging
|
||||
if pr.ID > 0 {
|
||||
diffCount, err := gitrepo.GetDivergingCommits(ctx, pr.BaseRepo, pr.BaseBranch, pr.GetGitHeadRefName())
|
||||
if err != nil {
|
||||
return err
|
||||
} else if diffCount.Behind == 0 {
|
||||
return fmt.Errorf("HeadBranch of PR %d is up to date", pr.Index)
|
||||
}
|
||||
}
|
||||
|
||||
if err := pr.LoadHeadRepo(ctx); err != nil {
|
||||
log.Error("unable to load HeadRepo for PR %-v during update-by-merge: %v", pr, err)
|
||||
return fmt.Errorf("unable to load HeadRepo for PR[%d] during update-by-merge: %w", pr.ID, err)
|
||||
@@ -96,92 +100,114 @@ func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.
|
||||
return err
|
||||
}
|
||||
|
||||
// IsUserAllowedToUpdate check if user is allowed to update PR with given permissions and branch protections
|
||||
// update PR means send new commits to PR head branch from base branch
|
||||
func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest, user *user_model.User) (mergeAllowed, rebaseAllowed bool, err error) {
|
||||
if pull.Flow == issues_model.PullRequestFlowAGit {
|
||||
return false, false, nil
|
||||
}
|
||||
// isUserAllowedToPushOrForcePushInRepoBranch checks whether user is allowed to push or force push in the given repo and branch
|
||||
// it will check both user permission and branch protection rules
|
||||
func isUserAllowedToPushOrForcePushInRepoBranch(ctx context.Context, user *user_model.User, repo *repo_model.Repository, branch string) (pushAllowed, forcePushAllowed bool, err error) {
|
||||
if user == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
headRepoPerm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, user)
|
||||
|
||||
// 1. check user push permission on the given repository
|
||||
repoPerm, err := access_model.GetDoerRepoPermission(ctx, repo, user)
|
||||
if err != nil {
|
||||
if repo_model.IsErrUnitTypeNotExist(err) {
|
||||
return false, false, nil
|
||||
}
|
||||
return false, false, err
|
||||
}
|
||||
pushAllowed = repoPerm.CanWrite(unit.TypeCode)
|
||||
forcePushAllowed = pushAllowed
|
||||
|
||||
// 2. check branch protection whether user can push or force push
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, repo.ID, branch)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
if pb != nil { // override previous results if there is a branch protection rule
|
||||
pb.Repo = repo
|
||||
pushAllowed = pb.CanUserPush(ctx, user)
|
||||
forcePushAllowed = pb.CanUserForcePush(ctx, user)
|
||||
}
|
||||
return pushAllowed, forcePushAllowed, nil
|
||||
}
|
||||
|
||||
// IsUserAllowedToUpdate check if user is allowed to update PR with given permissions and branch protections
|
||||
// update PR means send new commits to PR head branch from base branch
|
||||
func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest, user *user_model.User) (pushAllowed, rebaseAllowed bool, err error) {
|
||||
if user == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
if err := pull.LoadBaseRepo(ctx); err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
if err := pull.LoadHeadRepo(ctx); err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
// 1. check base repository's AllowRebaseUpdate configuration
|
||||
// 1. check whether pull request enabled.
|
||||
prBaseUnit, err := pull.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
|
||||
if repo_model.IsErrUnitTypeNotExist(err) {
|
||||
return false, false, nil // the PR unit is disabled in base repo means no update allowed
|
||||
} else if err != nil {
|
||||
return false, false, fmt.Errorf("get base repo unit: %v", err)
|
||||
}
|
||||
|
||||
// 2. only support Github style pull request
|
||||
if pull.Flow == issues_model.PullRequestFlowAGit {
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
// 3. check user push permission on head repository
|
||||
pushAllowed, rebaseAllowed, err = isUserAllowedToPushOrForcePushInRepoBranch(ctx, user, pull.HeadRepo, pull.HeadBranch)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
// 4. if the pull creator allows maintainer to edit, we need to check whether
|
||||
// user is a maintainer (has permission to merge into base branch) and inherit pull request poster's permission
|
||||
if pull.AllowMaintainerEdit && (!pushAllowed || !rebaseAllowed) {
|
||||
baseRepoPerm, err := access_model.GetDoerRepoPermission(ctx, pull.BaseRepo, user)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
userAllowedToMergePR, err := isUserAllowedToMergeInRepoBranch(ctx, pull.BaseRepoID, pull.BaseBranch, baseRepoPerm, user)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
if userAllowedToMergePR {
|
||||
// the user is maintainer (can merge PR), and this PR is allowed to be edited by maintainers,
|
||||
// then the user should inherit the PR poster's push/rebase permission for the head branch
|
||||
if err := pull.LoadIssue(ctx); err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
if err := pull.Issue.LoadPoster(ctx); err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
posterPushAllowed, posterRebaseAllowed, err := isUserAllowedToPushOrForcePushInRepoBranch(ctx, pull.Issue.Poster, pull.HeadRepo, pull.HeadBranch)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
if !pushAllowed {
|
||||
pushAllowed = posterPushAllowed
|
||||
}
|
||||
if !rebaseAllowed {
|
||||
rebaseAllowed = posterRebaseAllowed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. check base repository's AllowRebaseUpdate configuration
|
||||
// it is a config in base repo but controls the head (fork) repo's "Update" behavior
|
||||
{
|
||||
prBaseUnit, err := pull.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
|
||||
if repo_model.IsErrUnitTypeNotExist(err) {
|
||||
return false, false, nil // the PR unit is disabled in base repo
|
||||
} else if err != nil {
|
||||
return false, false, fmt.Errorf("get base repo unit: %v", err)
|
||||
}
|
||||
rebaseAllowed = prBaseUnit.PullRequestsConfig().AllowRebaseUpdate
|
||||
}
|
||||
|
||||
// 2. check head branch protection whether rebase is allowed, if pb not found then rebase depends on the above setting
|
||||
{
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pull.HeadRepoID, pull.HeadBranch)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
// If branch protected, disable rebase unless user is whitelisted to force push (which extends regular push)
|
||||
if pb != nil {
|
||||
pb.Repo = pull.HeadRepo
|
||||
rebaseAllowed = rebaseAllowed && pb.CanUserForcePush(ctx, user)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. check whether user has write access to head branch
|
||||
baseRepoPerm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, user)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
mergeAllowed, err = isUserAllowedToMergeInRepoBranch(ctx, pull.HeadRepoID, pull.HeadBranch, headRepoPerm, user)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
// 4. if the pull creator allows maintainer to edit, it means the write permissions of the head branch has been
|
||||
// granted to the user with write permission of the base repository
|
||||
if pull.AllowMaintainerEdit {
|
||||
mergeAllowedMaintainer, err := isUserAllowedToMergeInRepoBranch(ctx, pull.BaseRepoID, pull.BaseBranch, baseRepoPerm, user)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
mergeAllowed = mergeAllowed || mergeAllowedMaintainer
|
||||
}
|
||||
|
||||
// if merge is not allowed, rebase is also not allowed
|
||||
rebaseAllowed = rebaseAllowed && mergeAllowed
|
||||
|
||||
return mergeAllowed, rebaseAllowed, nil
|
||||
return pushAllowed, rebaseAllowed && prBaseUnit.PullRequestsConfig().AllowRebaseUpdate, nil
|
||||
}
|
||||
|
||||
// GetDiverging determines how many commits a PR is ahead or behind the PR base branch
|
||||
func GetDiverging(ctx context.Context, pr *issues_model.PullRequest) (*git.DivergeObject, error) {
|
||||
log.Trace("GetDiverging[%-v]: compare commits", pr)
|
||||
prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
|
||||
if err != nil {
|
||||
if !git_model.IsErrBranchNotExist(err) {
|
||||
log.Error("CreateTemporaryRepoForPR %-v: %v", pr, err)
|
||||
}
|
||||
return nil, err
|
||||
func syncCommitDivergence(ctx context.Context, pr *issues_model.PullRequest) error {
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
diff, err := git.GetDivergingCommits(ctx, prCtx.tmpBasePath, baseBranch, trackingBranch)
|
||||
return &diff, err
|
||||
divergence, err := gitrepo.GetDivergingCommits(ctx, pr.BaseRepo, pr.BaseBranch, pr.GetGitHeadRefName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pr.UpdateCommitDivergence(ctx, divergence.Ahead, divergence.Behind)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user