@@ -8,9 +8,7 @@ package issues
8
8
import (
9
9
"context"
10
10
"fmt"
11
- "regexp"
12
11
"strconv"
13
- "strings"
14
12
"unicode/utf8"
15
13
16
14
"code.gitea.io/gitea/models/db"
@@ -22,8 +20,6 @@ import (
22
20
"code.gitea.io/gitea/modules/git"
23
21
"code.gitea.io/gitea/modules/json"
24
22
"code.gitea.io/gitea/modules/log"
25
- "code.gitea.io/gitea/modules/markup"
26
- "code.gitea.io/gitea/modules/markup/markdown"
27
23
"code.gitea.io/gitea/modules/references"
28
24
"code.gitea.io/gitea/modules/structs"
29
25
"code.gitea.io/gitea/modules/timeutil"
@@ -687,31 +683,6 @@ func (c *Comment) LoadReview() error {
687
683
return c .loadReview (db .DefaultContext )
688
684
}
689
685
690
- var notEnoughLines = regexp .MustCompile (`fatal: file .* has only \d+ lines?` )
691
-
692
- func (c * Comment ) checkInvalidation (doer * user_model.User , repo * git.Repository , branch string ) error {
693
- // FIXME differentiate between previous and proposed line
694
- commit , err := repo .LineBlame (branch , repo .Path , c .TreePath , uint (c .UnsignedLine ()))
695
- if err != nil && (strings .Contains (err .Error (), "fatal: no such path" ) || notEnoughLines .MatchString (err .Error ())) {
696
- c .Invalidated = true
697
- return UpdateComment (c , doer )
698
- }
699
- if err != nil {
700
- return err
701
- }
702
- if c .CommitSHA != "" && c .CommitSHA != commit .ID .String () {
703
- c .Invalidated = true
704
- return UpdateComment (c , doer )
705
- }
706
- return nil
707
- }
708
-
709
- // CheckInvalidation checks if the line of code comment got changed by another commit.
710
- // If the line got changed the comment is going to be invalidated.
711
- func (c * Comment ) CheckInvalidation (repo * git.Repository , doer * user_model.User , branch string ) error {
712
- return c .checkInvalidation (doer , repo , branch )
713
- }
714
-
715
686
// DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes.
716
687
func (c * Comment ) DiffSide () string {
717
688
if c .Line < 0 {
@@ -1008,23 +979,28 @@ func GetCommentByID(ctx context.Context, id int64) (*Comment, error) {
1008
979
// FindCommentsOptions describes the conditions to Find comments
1009
980
type FindCommentsOptions struct {
1010
981
db.ListOptions
1011
- RepoID int64
1012
- IssueID int64
1013
- ReviewID int64
1014
- Since int64
1015
- Before int64
1016
- Line int64
1017
- TreePath string
1018
- Type CommentType
1019
- }
1020
-
1021
- func (opts * FindCommentsOptions ) toConds () builder.Cond {
982
+ RepoID int64
983
+ IssueID int64
984
+ ReviewID int64
985
+ Since int64
986
+ Before int64
987
+ Line int64
988
+ TreePath string
989
+ Type CommentType
990
+ IssueIDs []int64
991
+ Invalidated util.OptionalBool
992
+ }
993
+
994
+ // ToConds implements FindOptions interface
995
+ func (opts * FindCommentsOptions ) ToConds () builder.Cond {
1022
996
cond := builder .NewCond ()
1023
997
if opts .RepoID > 0 {
1024
998
cond = cond .And (builder.Eq {"issue.repo_id" : opts .RepoID })
1025
999
}
1026
1000
if opts .IssueID > 0 {
1027
1001
cond = cond .And (builder.Eq {"comment.issue_id" : opts .IssueID })
1002
+ } else if len (opts .IssueIDs ) > 0 {
1003
+ cond = cond .And (builder .In ("comment.issue_id" , opts .IssueIDs ))
1028
1004
}
1029
1005
if opts .ReviewID > 0 {
1030
1006
cond = cond .And (builder.Eq {"comment.review_id" : opts .ReviewID })
@@ -1044,13 +1020,16 @@ func (opts *FindCommentsOptions) toConds() builder.Cond {
1044
1020
if len (opts .TreePath ) > 0 {
1045
1021
cond = cond .And (builder.Eq {"comment.tree_path" : opts .TreePath })
1046
1022
}
1023
+ if ! opts .Invalidated .IsNone () {
1024
+ cond = cond .And (builder.Eq {"comment.invalidated" : opts .Invalidated .IsTrue ()})
1025
+ }
1047
1026
return cond
1048
1027
}
1049
1028
1050
1029
// FindComments returns all comments according options
1051
1030
func FindComments (ctx context.Context , opts * FindCommentsOptions ) ([]* Comment , error ) {
1052
1031
comments := make ([]* Comment , 0 , 10 )
1053
- sess := db .GetEngine (ctx ).Where (opts .toConds ())
1032
+ sess := db .GetEngine (ctx ).Where (opts .ToConds ())
1054
1033
if opts .RepoID > 0 {
1055
1034
sess .Join ("INNER" , "issue" , "issue.id = comment.issue_id" )
1056
1035
}
@@ -1069,13 +1048,19 @@ func FindComments(ctx context.Context, opts *FindCommentsOptions) ([]*Comment, e
1069
1048
1070
1049
// CountComments count all comments according options by ignoring pagination
1071
1050
func CountComments (opts * FindCommentsOptions ) (int64 , error ) {
1072
- sess := db .GetEngine (db .DefaultContext ).Where (opts .toConds ())
1051
+ sess := db .GetEngine (db .DefaultContext ).Where (opts .ToConds ())
1073
1052
if opts .RepoID > 0 {
1074
1053
sess .Join ("INNER" , "issue" , "issue.id = comment.issue_id" )
1075
1054
}
1076
1055
return sess .Count (& Comment {})
1077
1056
}
1078
1057
1058
+ // UpdateCommentInvalidate updates comment invalidated column
1059
+ func UpdateCommentInvalidate (ctx context.Context , c * Comment ) error {
1060
+ _ , err := db .GetEngine (ctx ).ID (c .ID ).Cols ("invalidated" ).Update (c )
1061
+ return err
1062
+ }
1063
+
1079
1064
// UpdateComment updates information of comment.
1080
1065
func UpdateComment (c * Comment , doer * user_model.User ) error {
1081
1066
ctx , committer , err := db .TxContext (db .DefaultContext )
@@ -1134,120 +1119,6 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
1134
1119
return DeleteReaction (ctx , & ReactionOptions {CommentID : comment .ID })
1135
1120
}
1136
1121
1137
- // CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS
1138
- type CodeComments map [string ]map [int64 ][]* Comment
1139
-
1140
- // FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line
1141
- func FetchCodeComments (ctx context.Context , issue * Issue , currentUser * user_model.User ) (CodeComments , error ) {
1142
- return fetchCodeCommentsByReview (ctx , issue , currentUser , nil )
1143
- }
1144
-
1145
- func fetchCodeCommentsByReview (ctx context.Context , issue * Issue , currentUser * user_model.User , review * Review ) (CodeComments , error ) {
1146
- pathToLineToComment := make (CodeComments )
1147
- if review == nil {
1148
- review = & Review {ID : 0 }
1149
- }
1150
- opts := FindCommentsOptions {
1151
- Type : CommentTypeCode ,
1152
- IssueID : issue .ID ,
1153
- ReviewID : review .ID ,
1154
- }
1155
-
1156
- comments , err := findCodeComments (ctx , opts , issue , currentUser , review )
1157
- if err != nil {
1158
- return nil , err
1159
- }
1160
-
1161
- for _ , comment := range comments {
1162
- if pathToLineToComment [comment .TreePath ] == nil {
1163
- pathToLineToComment [comment .TreePath ] = make (map [int64 ][]* Comment )
1164
- }
1165
- pathToLineToComment [comment.TreePath ][comment.Line ] = append (pathToLineToComment [comment.TreePath ][comment.Line ], comment )
1166
- }
1167
- return pathToLineToComment , nil
1168
- }
1169
-
1170
- func findCodeComments (ctx context.Context , opts FindCommentsOptions , issue * Issue , currentUser * user_model.User , review * Review ) ([]* Comment , error ) {
1171
- var comments []* Comment
1172
- if review == nil {
1173
- review = & Review {ID : 0 }
1174
- }
1175
- conds := opts .toConds ()
1176
- if review .ID == 0 {
1177
- conds = conds .And (builder.Eq {"invalidated" : false })
1178
- }
1179
- e := db .GetEngine (ctx )
1180
- if err := e .Where (conds ).
1181
- Asc ("comment.created_unix" ).
1182
- Asc ("comment.id" ).
1183
- Find (& comments ); err != nil {
1184
- return nil , err
1185
- }
1186
-
1187
- if err := issue .LoadRepo (ctx ); err != nil {
1188
- return nil , err
1189
- }
1190
-
1191
- if err := CommentList (comments ).LoadPosters (ctx ); err != nil {
1192
- return nil , err
1193
- }
1194
-
1195
- // Find all reviews by ReviewID
1196
- reviews := make (map [int64 ]* Review )
1197
- ids := make ([]int64 , 0 , len (comments ))
1198
- for _ , comment := range comments {
1199
- if comment .ReviewID != 0 {
1200
- ids = append (ids , comment .ReviewID )
1201
- }
1202
- }
1203
- if err := e .In ("id" , ids ).Find (& reviews ); err != nil {
1204
- return nil , err
1205
- }
1206
-
1207
- n := 0
1208
- for _ , comment := range comments {
1209
- if re , ok := reviews [comment .ReviewID ]; ok && re != nil {
1210
- // If the review is pending only the author can see the comments (except if the review is set)
1211
- if review .ID == 0 && re .Type == ReviewTypePending &&
1212
- (currentUser == nil || currentUser .ID != re .ReviewerID ) {
1213
- continue
1214
- }
1215
- comment .Review = re
1216
- }
1217
- comments [n ] = comment
1218
- n ++
1219
-
1220
- if err := comment .LoadResolveDoer (); err != nil {
1221
- return nil , err
1222
- }
1223
-
1224
- if err := comment .LoadReactions (issue .Repo ); err != nil {
1225
- return nil , err
1226
- }
1227
-
1228
- var err error
1229
- if comment .RenderedContent , err = markdown .RenderString (& markup.RenderContext {
1230
- Ctx : ctx ,
1231
- URLPrefix : issue .Repo .Link (),
1232
- Metas : issue .Repo .ComposeMetas (),
1233
- }, comment .Content ); err != nil {
1234
- return nil , err
1235
- }
1236
- }
1237
- return comments [:n ], nil
1238
- }
1239
-
1240
- // FetchCodeCommentsByLine fetches the code comments for a given treePath and line number
1241
- func FetchCodeCommentsByLine (ctx context.Context , issue * Issue , currentUser * user_model.User , treePath string , line int64 ) ([]* Comment , error ) {
1242
- opts := FindCommentsOptions {
1243
- Type : CommentTypeCode ,
1244
- IssueID : issue .ID ,
1245
- TreePath : treePath ,
1246
- Line : line ,
1247
- }
1248
- return findCodeComments (ctx , opts , issue , currentUser , nil )
1249
- }
1250
-
1251
1122
// UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id
1252
1123
func UpdateCommentsMigrationsByType (tp structs.GitServiceType , originalAuthorID string , posterID int64 ) error {
1253
1124
_ , err := db .GetEngine (db .DefaultContext ).Table ("comment" ).
0 commit comments