Skip to content

Commit 36943e5

Browse files
6543lafriks
andcommitted
Add "Update Branch" button to Pull Requests (#9784)
* add Divergence * add Update Button * first working version * re-use code * split raw merge commands and db-change functions (notify, cache, ...) * use rawMerge (remove redundant code) * own function to get Diverging of PRs * use FlashError * correct Error Msg * hook is triggerd ... so remove comment * add "branch2" to "user2/repo1" because it unit-test "TestPullView_ReviewerMissed" use it but dont exist jet :/ * move GetPerm to IsUserAllowedToUpdate * add Flash Success MSG * imprufe code - remove useless js chage * fix-lint * TEST: add PullRequest ID:5 Repo: user2/repo1 Base: branch1 Head: pr-to-update * correct comments * make PR5 outdated * fix Tests * WIP: add pull update test * update revs * update locales * working TEST * update UI * misspell * change style * add 1s delay so rev exist * move row up (before merge row) * fix lint nit * UI remove divider * Update style * nits * do it right * introduce IsSameRepo * remove useless check Co-authored-by: Lauris BH <[email protected]>
1 parent 9f40bb0 commit 36943e5

32 files changed

+489
-68
lines changed

integrations/api_issue_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,15 @@ func TestAPISearchIssue(t *testing.T) {
134134
var apiIssues []*api.Issue
135135
DecodeJSON(t, resp, &apiIssues)
136136

137-
assert.Len(t, apiIssues, 8)
137+
assert.Len(t, apiIssues, 9)
138138

139139
query := url.Values{}
140140
query.Add("token", token)
141141
link.RawQuery = query.Encode()
142142
req = NewRequest(t, "GET", link.String())
143143
resp = session.MakeRequest(t, req, http.StatusOK)
144144
DecodeJSON(t, resp, &apiIssues)
145-
assert.Len(t, apiIssues, 8)
145+
assert.Len(t, apiIssues, 9)
146146

147147
query.Add("state", "closed")
148148
link.RawQuery = query.Encode()
@@ -163,5 +163,5 @@ func TestAPISearchIssue(t *testing.T) {
163163
req = NewRequest(t, "GET", link.String())
164164
resp = session.MakeRequest(t, req, http.StatusOK)
165165
DecodeJSON(t, resp, &apiIssues)
166-
assert.Len(t, apiIssues, 0)
166+
assert.Len(t, apiIssues, 1)
167167
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
65f1bf27bc3bf70f64657658635e66094edbcb4d refs/heads/master
2+
985f0301dba5e7b34be866819cd15ad3d8f508ee refs/heads/branch2
3+
62fb502a7172d4453f0322a2cc85bddffa57f07a refs/heads/pr-to-update
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
985f0301dba5e7b34be866819cd15ad3d8f508ee
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
62fb502a7172d4453f0322a2cc85bddffa57f07a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
4a357436d925b5c974181ff12a994538ddc5a269
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
62fb502a7172d4453f0322a2cc85bddffa57f07a

integrations/pull_update_test.go

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright 2020 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package integrations
6+
7+
import (
8+
"fmt"
9+
"net/url"
10+
"testing"
11+
"time"
12+
13+
"code.gitea.io/gitea/models"
14+
"code.gitea.io/gitea/modules/repofiles"
15+
repo_module "code.gitea.io/gitea/modules/repository"
16+
pull_service "code.gitea.io/gitea/services/pull"
17+
repo_service "code.gitea.io/gitea/services/repository"
18+
19+
"github.com/stretchr/testify/assert"
20+
)
21+
22+
func TestPullUpdate(t *testing.T) {
23+
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
24+
//Create PR to test
25+
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
26+
org26 := models.AssertExistsAndLoadBean(t, &models.User{ID: 26}).(*models.User)
27+
pr := createOutdatedPR(t, user, org26)
28+
29+
//Test GetDiverging
30+
diffCount, err := pull_service.GetDiverging(pr)
31+
assert.NoError(t, err)
32+
assert.EqualValues(t, 1, diffCount.Behind)
33+
assert.EqualValues(t, 1, diffCount.Ahead)
34+
35+
message := fmt.Sprintf("Merge branch '%s' into %s", pr.BaseBranch, pr.HeadBranch)
36+
err = pull_service.Update(pr, user, message)
37+
assert.NoError(t, err)
38+
39+
//Test GetDiverging after update
40+
diffCount, err = pull_service.GetDiverging(pr)
41+
assert.NoError(t, err)
42+
assert.EqualValues(t, 0, diffCount.Behind)
43+
assert.EqualValues(t, 2, diffCount.Ahead)
44+
45+
})
46+
}
47+
48+
func createOutdatedPR(t *testing.T, actor, forkOrg *models.User) *models.PullRequest {
49+
baseRepo, err := repo_service.CreateRepository(actor, actor, models.CreateRepoOptions{
50+
Name: "repo-pr-update",
51+
Description: "repo-tmp-pr-update description",
52+
AutoInit: true,
53+
Gitignores: "C,C++",
54+
License: "MIT",
55+
Readme: "Default",
56+
IsPrivate: false,
57+
})
58+
assert.NoError(t, err)
59+
assert.NotEmpty(t, baseRepo)
60+
61+
headRepo, err := repo_module.ForkRepository(actor, forkOrg, baseRepo, "repo-pr-update", "desc")
62+
assert.NoError(t, err)
63+
assert.NotEmpty(t, headRepo)
64+
65+
//create a commit on base Repo
66+
_, err = repofiles.CreateOrUpdateRepoFile(baseRepo, actor, &repofiles.UpdateRepoFileOptions{
67+
TreePath: "File_A",
68+
Message: "Add File A",
69+
Content: "File A",
70+
IsNewFile: true,
71+
OldBranch: "master",
72+
NewBranch: "master",
73+
Author: &repofiles.IdentityOptions{
74+
Name: actor.Name,
75+
Email: actor.Email,
76+
},
77+
Committer: &repofiles.IdentityOptions{
78+
Name: actor.Name,
79+
Email: actor.Email,
80+
},
81+
Dates: &repofiles.CommitDateOptions{
82+
Author: time.Now(),
83+
Committer: time.Now(),
84+
},
85+
})
86+
assert.NoError(t, err)
87+
88+
//create a commit on head Repo
89+
_, err = repofiles.CreateOrUpdateRepoFile(headRepo, actor, &repofiles.UpdateRepoFileOptions{
90+
TreePath: "File_B",
91+
Message: "Add File on PR branch",
92+
Content: "File B",
93+
IsNewFile: true,
94+
OldBranch: "master",
95+
NewBranch: "newBranch",
96+
Author: &repofiles.IdentityOptions{
97+
Name: actor.Name,
98+
Email: actor.Email,
99+
},
100+
Committer: &repofiles.IdentityOptions{
101+
Name: actor.Name,
102+
Email: actor.Email,
103+
},
104+
Dates: &repofiles.CommitDateOptions{
105+
Author: time.Now(),
106+
Committer: time.Now(),
107+
},
108+
})
109+
assert.NoError(t, err)
110+
111+
//create Pull
112+
pullIssue := &models.Issue{
113+
RepoID: baseRepo.ID,
114+
Title: "Test Pull -to-update-",
115+
PosterID: actor.ID,
116+
Poster: actor,
117+
IsPull: true,
118+
}
119+
pullRequest := &models.PullRequest{
120+
HeadRepoID: headRepo.ID,
121+
BaseRepoID: baseRepo.ID,
122+
HeadBranch: "newBranch",
123+
BaseBranch: "master",
124+
HeadRepo: headRepo,
125+
BaseRepo: baseRepo,
126+
Type: models.PullRequestGitea,
127+
}
128+
err = pull_service.NewPullRequest(baseRepo, pullIssue, nil, nil, pullRequest, nil)
129+
assert.NoError(t, err)
130+
131+
issue := models.AssertExistsAndLoadBean(t, &models.Issue{Title: "Test Pull -to-update-"}).(*models.Issue)
132+
pr, err := models.GetPullRequestByIssueID(issue.ID)
133+
assert.NoError(t, err)
134+
135+
return pr
136+
}

integrations/repo_activity_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ func TestRepoActivity(t *testing.T) {
5656
list = htmlDoc.doc.Find("#merged-pull-requests").Next().Find("p.desc")
5757
assert.Len(t, list.Nodes, 1)
5858

59-
// Should be 2 merged proposed pull requests
59+
// Should be 3 merged proposed pull requests
6060
list = htmlDoc.doc.Find("#proposed-pull-requests").Next().Find("p.desc")
61-
assert.Len(t, list.Nodes, 2)
61+
assert.Len(t, list.Nodes, 3)
6262

6363
// Should be 3 new issues
6464
list = htmlDoc.doc.Find("#new-issues").Next().Find("p.desc")

models/fixtures/issue.yml

+12
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,15 @@
122122
created_unix: 946684830
123123
updated_unix: 999307200
124124
deadline_unix: 1019307200
125+
126+
-
127+
id: 11
128+
repo_id: 1
129+
index: 5
130+
poster_id: 1
131+
name: pull5
132+
content: content for the a pull request
133+
is_closed: false
134+
is_pull: true
135+
created_unix: 1579194806
136+
updated_unix: 1579194806

models/fixtures/pull_request.yml

+14-1
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,17 @@
4949
head_branch: branch1
5050
base_branch: master
5151
merge_base: abcdef1234567890
52-
has_merged: false
52+
has_merged: false
53+
54+
-
55+
id: 5 # this PR is outdated (one commit behind branch1 )
56+
type: 0 # gitea pull request
57+
status: 2 # mergable
58+
issue_id: 11
59+
index: 5
60+
head_repo_id: 1
61+
base_repo_id: 1
62+
head_branch: pr-to-update
63+
base_branch: branch1
64+
merge_base: 1234567890abcdef
65+
has_merged: false

models/fixtures/repository.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
is_private: false
88
num_issues: 2
99
num_closed_issues: 1
10-
num_pulls: 2
10+
num_pulls: 3
1111
num_closed_pulls: 0
1212
num_milestones: 3
1313
num_closed_milestones: 1

models/issue_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,8 @@ func TestIssue_SearchIssueIDsByKeyword(t *testing.T) {
276276

277277
total, ids, err = SearchIssueIDsByKeyword("for", []int64{1}, 10, 0)
278278
assert.NoError(t, err)
279-
assert.EqualValues(t, 4, total)
280-
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
279+
assert.EqualValues(t, 5, total)
280+
assert.EqualValues(t, []int64{1, 2, 3, 5, 11}, ids)
281281

282282
// issue1's comment id 2
283283
total, ids, err = SearchIssueIDsByKeyword("good", []int64{1}, 10, 0)
@@ -305,8 +305,8 @@ func testInsertIssue(t *testing.T, title, content string) {
305305
assert.True(t, has)
306306
assert.EqualValues(t, issue.Title, newIssue.Title)
307307
assert.EqualValues(t, issue.Content, newIssue.Content)
308-
// there are 4 issues and max index is 4 on repository 1, so this one should 5
309-
assert.EqualValues(t, 5, newIssue.Index)
308+
// there are 5 issues and max index is 5 on repository 1, so this one should 6
309+
assert.EqualValues(t, 6, newIssue.Index)
310310

311311
_, err = x.ID(issue.ID).Delete(new(Issue))
312312
assert.NoError(t, err)

models/issue_user_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func Test_newIssueUsers(t *testing.T) {
1717
newIssue := &Issue{
1818
RepoID: repo.ID,
1919
PosterID: 4,
20-
Index: 5,
20+
Index: 6,
2121
Title: "newTestIssueTitle",
2222
Content: "newTestIssueContent",
2323
}

models/pull.go

+5
Original file line numberDiff line numberDiff line change
@@ -742,3 +742,8 @@ func (pr *PullRequest) IsHeadEqualWithBranch(branchName string) (bool, error) {
742742
}
743743
return baseCommit.HasPreviousCommit(headCommit.ID)
744744
}
745+
746+
// IsSameRepo returns true if base repo and head repo is the same
747+
func (pr *PullRequest) IsSameRepo() bool {
748+
return pr.BaseRepoID == pr.HeadRepoID
749+
}

models/pull_test.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,11 @@ func TestPullRequestsNewest(t *testing.T) {
6161
Labels: []string{},
6262
})
6363
assert.NoError(t, err)
64-
assert.Equal(t, int64(2), count)
65-
if assert.Len(t, prs, 2) {
66-
assert.Equal(t, int64(2), prs[0].ID)
67-
assert.Equal(t, int64(1), prs[1].ID)
64+
assert.EqualValues(t, 3, count)
65+
if assert.Len(t, prs, 3) {
66+
assert.EqualValues(t, 5, prs[0].ID)
67+
assert.EqualValues(t, 2, prs[1].ID)
68+
assert.EqualValues(t, 1, prs[2].ID)
6869
}
6970
}
7071

@@ -77,10 +78,11 @@ func TestPullRequestsOldest(t *testing.T) {
7778
Labels: []string{},
7879
})
7980
assert.NoError(t, err)
80-
assert.Equal(t, int64(2), count)
81-
if assert.Len(t, prs, 2) {
82-
assert.Equal(t, int64(1), prs[0].ID)
83-
assert.Equal(t, int64(2), prs[1].ID)
81+
assert.EqualValues(t, 3, count)
82+
if assert.Len(t, prs, 3) {
83+
assert.EqualValues(t, 1, prs[0].ID)
84+
assert.EqualValues(t, 2, prs[1].ID)
85+
assert.EqualValues(t, 5, prs[2].ID)
8486
}
8587
}
8688

modules/indexer/issues/indexer_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func TestBleveSearchIssues(t *testing.T) {
6565

6666
ids, err = SearchIssuesByKeyword([]int64{1}, "for")
6767
assert.NoError(t, err)
68-
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
68+
assert.EqualValues(t, []int64{1, 2, 3, 5, 11}, ids)
6969

7070
ids, err = SearchIssuesByKeyword([]int64{1}, "good")
7171
assert.NoError(t, err)
@@ -89,7 +89,7 @@ func TestDBSearchIssues(t *testing.T) {
8989

9090
ids, err = SearchIssuesByKeyword([]int64{1}, "for")
9191
assert.NoError(t, err)
92-
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
92+
assert.EqualValues(t, []int64{1, 2, 3, 5, 11}, ids)
9393

9494
ids, err = SearchIssuesByKeyword([]int64{1}, "good")
9595
assert.NoError(t, err)

options/locale/locale_en-US.ini

+4
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,10 @@ pulls.open_unmerged_pull_exists = `You cannot perform a reopen operation because
10821082
pulls.status_checking = Some checks are pending
10831083
pulls.status_checks_success = All checks were successful
10841084
pulls.status_checks_error = Some checks failed
1085+
pulls.update_branch = Update branch
1086+
pulls.update_branch_success = Branch update was successful
1087+
pulls.update_not_allowed = You are not allowed to update branch
1088+
pulls.outdated_with_base_branch = This branch is out-of-date with the base branch
10851089
10861090
milestones.new = New Milestone
10871091
milestones.open_tab = %d Open

0 commit comments

Comments
 (0)