Skip to content

Commit 23ed657

Browse files
committed
Add tests
1 parent c5d74e5 commit 23ed657

File tree

5 files changed

+155
-5
lines changed

5 files changed

+155
-5
lines changed

routers/web/repo/pull.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,7 +1583,10 @@ func UpdatePullRequestTarget(ctx *context.Context) {
15831583
}
15841584

15851585
if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.Doer, targetBranch); err != nil {
1586-
if issues_model.IsErrPullRequestAlreadyExists(err) {
1586+
switch {
1587+
case git_model.IsErrBranchNotExist(err):
1588+
ctx.HTTPError(http.StatusBadRequest)
1589+
case issues_model.IsErrPullRequestAlreadyExists(err):
15871590
err := err.(issues_model.ErrPullRequestAlreadyExists)
15881591

15891592
RepoRelPath := ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
@@ -1594,31 +1597,31 @@ func UpdatePullRequestTarget(ctx *context.Context) {
15941597
"error": err.Error(),
15951598
"user_error": errorMessage,
15961599
})
1597-
} else if issues_model.IsErrIssueIsClosed(err) {
1600+
case issues_model.IsErrIssueIsClosed(err):
15981601
errorMessage := ctx.Tr("repo.pulls.is_closed")
15991602

16001603
ctx.Flash.Error(errorMessage)
16011604
ctx.JSON(http.StatusConflict, map[string]any{
16021605
"error": err.Error(),
16031606
"user_error": errorMessage,
16041607
})
1605-
} else if pull_service.IsErrPullRequestHasMerged(err) {
1608+
case pull_service.IsErrPullRequestHasMerged(err):
16061609
errorMessage := ctx.Tr("repo.pulls.has_merged")
16071610

16081611
ctx.Flash.Error(errorMessage)
16091612
ctx.JSON(http.StatusConflict, map[string]any{
16101613
"error": err.Error(),
16111614
"user_error": errorMessage,
16121615
})
1613-
} else if git_model.IsErrBranchesEqual(err) {
1616+
case git_model.IsErrBranchesEqual(err):
16141617
errorMessage := ctx.Tr("repo.pulls.nothing_to_compare")
16151618

16161619
ctx.Flash.Error(errorMessage)
16171620
ctx.JSON(http.StatusBadRequest, map[string]any{
16181621
"error": err.Error(),
16191622
"user_error": errorMessage,
16201623
})
1621-
} else {
1624+
default:
16221625
ctx.ServerError("UpdatePullRequestTarget", err)
16231626
}
16241627
return

services/pull/comment.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *iss
6363
var data issues_model.PushActionContent
6464
if opts.IsForcePush {
6565
data.CommitIDs = []string{oldCommitID, newCommitID}
66+
data.IsForcePush = true
6667
} else {
6768
data.CommitIDs, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch)
6869
if err != nil {

services/pull/pull.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,17 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
243243
}
244244
}
245245

246+
exist, err := git_model.IsBranchExist(ctx, pr.BaseRepoID, targetBranch)
247+
if err != nil {
248+
return err
249+
}
250+
if !exist {
251+
return git_model.ErrBranchNotExist{
252+
RepoID: pr.BaseRepoID,
253+
BranchName: targetBranch,
254+
}
255+
}
256+
246257
// Check if branches are equal
247258
branchesEqual, err := IsHeadEqualWithBranch(ctx, pr, targetBranch)
248259
if err != nil {

tests/integration/git_helper_for_declarative_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,18 @@ func doGitPull(dstPath string, args ...string) func(*testing.T) {
205205
assert.NoError(t, err)
206206
}
207207
}
208+
209+
func doGitCommit(dstPath, commitMessage string) func(*testing.T) {
210+
return func(t *testing.T) {
211+
signature := git.Signature{
212+
Email: "test@test.test",
213+
Name: "test",
214+
When: time.Now(),
215+
}
216+
assert.NoError(t, git.CommitChanges(t.Context(), dstPath, git.CommitChangesOptions{
217+
Committer: &signature,
218+
Author: &signature,
219+
Message: commitMessage,
220+
}))
221+
}
222+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package integration
5+
6+
import (
7+
"fmt"
8+
"net/http"
9+
"net/url"
10+
"os"
11+
"testing"
12+
"time"
13+
14+
issues_model "code.gitea.io/gitea/models/issues"
15+
"code.gitea.io/gitea/models/unittest"
16+
"code.gitea.io/gitea/modules/git/gitcmd"
17+
issues_service "code.gitea.io/gitea/services/issue"
18+
19+
"github.com/stretchr/testify/assert"
20+
)
21+
22+
func TestPull_RebaseComment(t *testing.T) {
23+
onGiteaRun(t, func(t *testing.T, u *url.URL) {
24+
session := loginUser(t, "user1")
25+
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
26+
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
27+
testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
28+
29+
// create a conflict line on user2/repo1:master README.md
30+
testEditFile(t, session, "user2", "repo1", "master", "README.md", "Hello, World (Edited Conflicted)\n")
31+
32+
// Now the pull request status should be conflicted
33+
prIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: "This is a pull title"})
34+
assert.NoError(t, prIssue.LoadPullRequest(t.Context()))
35+
assert.Equal(t, issues_model.PullRequestStatusConflict, prIssue.PullRequest.Status)
36+
assert.NoError(t, prIssue.PullRequest.LoadBaseRepo(t.Context()))
37+
assert.Equal(t, "user2/repo1", prIssue.PullRequest.BaseRepo.FullName())
38+
assert.NoError(t, prIssue.PullRequest.LoadHeadRepo(t.Context()))
39+
assert.Equal(t, "user1/repo1", prIssue.PullRequest.HeadRepo.FullName())
40+
41+
dstPath := t.TempDir()
42+
u.Path = "/user2/repo1.git"
43+
doGitClone(dstPath, u)(t)
44+
doGitCreateBranch(dstPath, "dev")(t)
45+
content, err := os.ReadFile(dstPath + "/README.md")
46+
assert.NoError(t, err)
47+
assert.Equal(t, "Hello, World (Edited Conflicted)\n", string(content))
48+
49+
err = os.WriteFile(dstPath+"/README.md", []byte("Hello, World (Edited Conflict Resolved)\n"), 0o644)
50+
assert.NoError(t, err)
51+
_, _, err = gitcmd.NewCommand().AddArguments("add", "--all").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath})
52+
assert.NoError(t, err)
53+
doGitCommit(dstPath, "Resolve conflict")(t)
54+
55+
// do force push
56+
u.Path = "/user1/repo1.git"
57+
u.User = url.UserPassword("user1", userPassword)
58+
doGitAddRemote(dstPath, "fork", u)(t)
59+
// non force push will fail
60+
_, _, err = gitcmd.NewCommand().AddArguments("push", "fork", "dev:master").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath})
61+
assert.Error(t, err)
62+
_, _, err = gitcmd.NewCommand().AddArguments("push", "--force", "fork", "dev:master").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath})
63+
assert.NoError(t, err)
64+
65+
time.Sleep(time.Second) // wait for pull request conflict checking
66+
67+
// reload the pr
68+
prIssue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: "This is a pull title"})
69+
assert.NoError(t, prIssue.LoadPullRequest(t.Context()))
70+
assert.Equal(t, issues_model.PullRequestStatusMergeable, prIssue.PullRequest.Status)
71+
comments, err := issues_model.FindComments(t.Context(), &issues_model.FindCommentsOptions{
72+
IssueID: prIssue.ID,
73+
Type: issues_model.CommentTypeUndefined, // get all comments type
74+
})
75+
assert.NoError(t, err)
76+
lastComment := comments[len(comments)-1]
77+
err = issues_service.LoadCommentPushCommits(t.Context(), lastComment)
78+
assert.NoError(t, err)
79+
assert.True(t, lastComment.IsForcePush)
80+
})
81+
}
82+
83+
func TestPull_RetargetComment(t *testing.T) {
84+
onGiteaRun(t, func(t *testing.T, u *url.URL) {
85+
session := loginUser(t, "user1")
86+
testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "")
87+
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
88+
testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title")
89+
90+
session2 := loginUser(t, "user2")
91+
// create a non-conflict branch dev from master
92+
testCreateBranch(t, session2, "user2", "repo1", "branch/master", "dev", http.StatusSeeOther)
93+
94+
// create a conflict line on user2/repo1:master README.md
95+
testEditFile(t, session2, "user2", "repo1", "master", "README.md", "Hello, World (Edited Conflicted)\n")
96+
97+
// Now the pull request status should be conflicted
98+
prIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: "This is a pull title"})
99+
assert.NoError(t, prIssue.LoadPullRequest(t.Context()))
100+
assert.Equal(t, issues_model.PullRequestStatusConflict, prIssue.PullRequest.Status)
101+
assert.NoError(t, prIssue.PullRequest.LoadBaseRepo(t.Context()))
102+
assert.Equal(t, "user2/repo1", prIssue.PullRequest.BaseRepo.FullName())
103+
assert.NoError(t, prIssue.PullRequest.LoadHeadRepo(t.Context()))
104+
assert.Equal(t, "user1/repo1", prIssue.PullRequest.HeadRepo.FullName())
105+
106+
// do retarget
107+
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/user2/repo1/pull/%d/target_branch", prIssue.PullRequest.Index), map[string]string{
108+
"_csrf": GetUserCSRFToken(t, session2),
109+
"target_branch": "dev",
110+
})
111+
session2.MakeRequest(t, req, http.StatusOK)
112+
113+
time.Sleep(time.Second) // wait for pull request conflict checking
114+
115+
// reload the pr
116+
prIssue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: "This is a pull title"})
117+
assert.NoError(t, prIssue.LoadPullRequest(t.Context()))
118+
assert.Equal(t, issues_model.PullRequestStatusMergeable, prIssue.PullRequest.Status)
119+
})
120+
}

0 commit comments

Comments
 (0)