mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-06 07:38:42 +00:00
Fix #36905 The changes focus on force-push PR timeline handling and commit range calculation: - Reworked pull-request push comment creation to use a new `gitrepo.GetCommitIDsBetweenReverse` helper, with special handling for force pushes (merge-base based range, tolerate missing/invalid old commits, and keep force-push timeline entries). - Added `Comment.GetPushActionContent` to parse push comment payloads and used it to delete only non-force-push push comments during force pushes. - Removed the old `Repository.CommitsBetweenNotBase` helper from `modules/git/repo_commit.go` in favor of the new commit ID range helper. - Added tests for `GetCommitIDsBetweenReverse` (normal range, `notRef` filtering, fallback branch usage) and expanded pull comment tests to cover force-push edge cases. <img width="989" height="563" alt="image" src="https://github.com/user-attachments/assets/a01e1bc2-fa8a-4028-8a35-d484e601ff3b" /> --------- Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com> Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
124 lines
4.8 KiB
Go
124 lines
4.8 KiB
Go
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package pull
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
issues_model "code.gitea.io/gitea/models/issues"
|
|
"code.gitea.io/gitea/models/unittest"
|
|
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/json"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCreatePushPullCommentForcePushDeletesOldComments(t *testing.T) {
|
|
require.NoError(t, unittest.PrepareTestDatabase())
|
|
pusher := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
|
require.NoError(t, pr.LoadIssue(t.Context()))
|
|
require.NoError(t, pr.LoadBaseRepo(t.Context()))
|
|
|
|
gitRepo, err := gitrepo.OpenRepository(t.Context(), pr.BaseRepo)
|
|
require.NoError(t, err)
|
|
defer gitRepo.Close()
|
|
|
|
insertCommitComment := func(t *testing.T, content issues_model.PushActionContent) {
|
|
contentJSON, _ := json.Marshal(content)
|
|
_, err := issues_model.CreateComment(t.Context(), &issues_model.CreateCommentOptions{
|
|
Type: issues_model.CommentTypePullRequestPush,
|
|
Doer: pusher,
|
|
Repo: pr.BaseRepo,
|
|
Issue: pr.Issue,
|
|
Content: string(contentJSON),
|
|
})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
assertCommitCommentCount := func(t *testing.T, expectedTotalCount, expectedForcePushCount int) {
|
|
comments, err := issues_model.FindComments(t.Context(), &issues_model.FindCommentsOptions{
|
|
IssueID: pr.IssueID,
|
|
Type: issues_model.CommentTypePullRequestPush,
|
|
})
|
|
require.NoError(t, err)
|
|
totalCount, forcePushCount := len(comments), 0
|
|
for _, comment := range comments {
|
|
pushData, err := comment.GetPushActionContent()
|
|
require.NoError(t, err)
|
|
if pushData.IsForcePush {
|
|
forcePushCount++
|
|
}
|
|
}
|
|
assert.Equal(t, expectedTotalCount, totalCount, "total comment count should match")
|
|
assert.Equal(t, expectedForcePushCount, forcePushCount, "force push comment count should match")
|
|
}
|
|
|
|
t.Run("base-branch-only", func(t *testing.T) {
|
|
require.NoError(t, db.TruncateBeans(t.Context(), &issues_model.Comment{}))
|
|
insertCommitComment(t, issues_model.PushActionContent{})
|
|
insertCommitComment(t, issues_model.PushActionContent{})
|
|
assertCommitCommentCount(t, 2, 0)
|
|
|
|
baseCommit, err := gitRepo.GetBranchCommit(pr.BaseBranch)
|
|
assert.NoError(t, err)
|
|
|
|
// force push, the old push comments should be deleted, and one new force-push comment should be created.
|
|
// the pushed branch is the same as base branch, so no commit between old and new commit, no regular push comment
|
|
comment, _, err := CreatePushPullComment(t.Context(), pusher, pr, baseCommit.ID.String(), baseCommit.ID.String(), true)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, comment)
|
|
assertCommitCommentCount(t, 1, 1)
|
|
|
|
createdData, err := comment.GetPushActionContent()
|
|
require.NoError(t, err)
|
|
assert.True(t, createdData.IsForcePush)
|
|
assert.Equal(t, []string{baseCommit.ID.String(), baseCommit.ID.String()}, createdData.CommitIDs)
|
|
})
|
|
|
|
t.Run("force-push-ignores-missing-old-commit", func(t *testing.T) {
|
|
require.NoError(t, db.TruncateBeans(t.Context(), &issues_model.Comment{}))
|
|
headCommit, err := gitRepo.GetBranchCommit(pr.HeadBranch)
|
|
require.NoError(t, err)
|
|
|
|
commitIDZero := git.Sha1ObjectFormat.EmptyObjectID().String()
|
|
comment, _, err := CreatePushPullComment(t.Context(), pusher, pr, commitIDZero, headCommit.ID.String(), true)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, comment)
|
|
createdData, err := comment.GetPushActionContent()
|
|
require.NoError(t, err)
|
|
assert.True(t, createdData.IsForcePush)
|
|
assert.Equal(t, []string{commitIDZero, headCommit.ID.String()}, createdData.CommitIDs)
|
|
assertCommitCommentCount(t, 2, 1)
|
|
|
|
// force push again, the old force push comment should not be deleted, new we have 2 force push comments.
|
|
_, _, err = CreatePushPullComment(t.Context(), pusher, pr, commitIDZero, headCommit.ID.String(), true)
|
|
require.NoError(t, err)
|
|
assertCommitCommentCount(t, 3, 2)
|
|
})
|
|
|
|
t.Run("head-vs-base-branch", func(t *testing.T) {
|
|
require.NoError(t, db.TruncateBeans(t.Context(), &issues_model.Comment{}))
|
|
insertCommitComment(t, issues_model.PushActionContent{})
|
|
insertCommitComment(t, issues_model.PushActionContent{})
|
|
insertCommitComment(t, issues_model.PushActionContent{})
|
|
insertCommitComment(t, issues_model.PushActionContent{})
|
|
assertCommitCommentCount(t, 4, 0)
|
|
|
|
baseCommit, err := gitRepo.GetBranchCommit(pr.BaseBranch)
|
|
require.NoError(t, err)
|
|
headCommit, err := gitRepo.GetBranchCommit(pr.HeadBranch)
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = CreatePushPullComment(t.Context(), pusher, pr, baseCommit.ID.String(), headCommit.ID.String(), true)
|
|
require.NoError(t, err)
|
|
// 2 comments should exist now: one regular push comment and one force-push comment.
|
|
assertCommitCommentCount(t, 2, 1)
|
|
})
|
|
}
|