Skip to content

Commit 9c9c334

Browse files
authored
Prevent NPE on commenting on lines with invalidated comments (with migration) (#12549)
* Prevent NPE on commenting on lines with invalidated comments Only check for a review if we are replying to a previous review. Prevent the NPE in #12239 by assuming that a comment without a Review is non-pending. Fix #12239 Signed-off-by: Andrew Thornton <[email protected]> * Add hack around to show the broken comments Signed-off-by: Andrew Thornton <[email protected]> * Add migration and remove template hacks Signed-off-by: Andrew Thornton <[email protected]>
1 parent c6943cc commit 9c9c334

File tree

3 files changed

+135
-1
lines changed

3 files changed

+135
-1
lines changed

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ var migrations = []Migration{
226226
NewMigration("Increase Language field to 50 in LanguageStats", increaseLanguageField),
227227
// v146 -> v147
228228
NewMigration("Add projects info to repository table", addProjectsInfo),
229+
// v147 -> v148
230+
NewMigration("create review for 0 review id code comments", createReviewsForCodeComments),
229231
}
230232

231233
// GetCurrentDBVersion returns the current db version

models/migrations/v147.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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 migrations
6+
7+
import (
8+
"code.gitea.io/gitea/modules/timeutil"
9+
10+
"xorm.io/xorm"
11+
)
12+
13+
func createReviewsForCodeComments(x *xorm.Engine) error {
14+
// Review
15+
type Review struct {
16+
ID int64 `xorm:"pk autoincr"`
17+
Type int
18+
ReviewerID int64 `xorm:"index"`
19+
OriginalAuthor string
20+
OriginalAuthorID int64
21+
IssueID int64 `xorm:"index"`
22+
Content string `xorm:"TEXT"`
23+
// Official is a review made by an assigned approver (counts towards approval)
24+
Official bool `xorm:"NOT NULL DEFAULT false"`
25+
CommitID string `xorm:"VARCHAR(40)"`
26+
Stale bool `xorm:"NOT NULL DEFAULT false"`
27+
28+
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
29+
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
30+
}
31+
32+
const ReviewTypeComment = 2
33+
34+
// Comment represents a comment in commit and issue page.
35+
type Comment struct {
36+
ID int64 `xorm:"pk autoincr"`
37+
Type int `xorm:"INDEX"`
38+
PosterID int64 `xorm:"INDEX"`
39+
OriginalAuthor string
40+
OriginalAuthorID int64
41+
IssueID int64 `xorm:"INDEX"`
42+
LabelID int64
43+
OldProjectID int64
44+
ProjectID int64
45+
OldMilestoneID int64
46+
MilestoneID int64
47+
AssigneeID int64
48+
RemovedAssignee bool
49+
ResolveDoerID int64
50+
OldTitle string
51+
NewTitle string
52+
OldRef string
53+
NewRef string
54+
DependentIssueID int64
55+
56+
CommitID int64
57+
Line int64 // - previous line / + proposed line
58+
TreePath string
59+
Content string `xorm:"TEXT"`
60+
61+
// Path represents the 4 lines of code cemented by this comment
62+
PatchQuoted string `xorm:"TEXT patch"`
63+
64+
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
65+
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
66+
67+
// Reference issue in commit message
68+
CommitSHA string `xorm:"VARCHAR(40)"`
69+
70+
ReviewID int64 `xorm:"index"`
71+
Invalidated bool
72+
73+
// Reference an issue or pull from another comment, issue or PR
74+
// All information is about the origin of the reference
75+
RefRepoID int64 `xorm:"index"` // Repo where the referencing
76+
RefIssueID int64 `xorm:"index"`
77+
RefCommentID int64 `xorm:"index"` // 0 if origin is Issue title or content (or PR's)
78+
RefAction int `xorm:"SMALLINT"` // What hapens if RefIssueID resolves
79+
RefIsPull bool
80+
}
81+
82+
if err := x.Sync2(new(Review), new(Comment)); err != nil {
83+
return err
84+
}
85+
sess := x.NewSession()
86+
defer sess.Close()
87+
if err := sess.Begin(); err != nil {
88+
return err
89+
}
90+
if err := sess.Where("review_id = 0 and type = 21").Iterate(new(Comment), func(idx int, bean interface{}) error {
91+
comment := bean.(*Comment)
92+
93+
review := &Review{
94+
Type: ReviewTypeComment,
95+
ReviewerID: comment.PosterID,
96+
IssueID: comment.IssueID,
97+
Official: false,
98+
CommitID: comment.CommitSHA,
99+
Stale: comment.Invalidated,
100+
OriginalAuthor: comment.OriginalAuthor,
101+
OriginalAuthorID: comment.OriginalAuthorID,
102+
CreatedUnix: comment.CreatedUnix,
103+
UpdatedUnix: comment.CreatedUnix,
104+
}
105+
if _, err := sess.NoAutoTime().Insert(review); err != nil {
106+
return err
107+
}
108+
109+
reviewComment := &Comment{
110+
Type: 22,
111+
PosterID: comment.PosterID,
112+
Content: "",
113+
IssueID: comment.IssueID,
114+
ReviewID: review.ID,
115+
OriginalAuthor: comment.OriginalAuthor,
116+
OriginalAuthorID: comment.OriginalAuthorID,
117+
CreatedUnix: comment.CreatedUnix,
118+
UpdatedUnix: comment.CreatedUnix,
119+
}
120+
if _, err := sess.NoAutoTime().Insert(reviewComment); err != nil {
121+
return err
122+
}
123+
124+
comment.ReviewID = review.ID
125+
_, err := sess.ID(comment.ID).Cols("review_id").NoAutoTime().Update(comment)
126+
return err
127+
}); err != nil {
128+
return err
129+
}
130+
131+
return sess.Commit()
132+
}

services/pull/review.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func CreateCodeComment(doer *models.User, gitRepo *git.Repository, issue *models
2929
// - Comments that are part of a review
3030
// - Comments that reply to an existing review
3131

32-
if !isReview {
32+
if !isReview && replyReviewID != 0 {
3333
// It's not part of a review; maybe a reply to a review comment or a single comment.
3434
// Check if there are reviews for that line already; if there are, this is a reply
3535
if existsReview, err = models.ReviewExists(issue, treePath, line); err != nil {

0 commit comments

Comments
 (0)