@@ -8,9 +8,7 @@ package issues
88import (
99 "context"
1010 "fmt"
11- "regexp"
1211 "strconv"
13- "strings"
1412 "unicode/utf8"
1513
1614 "code.gitea.io/gitea/models/db"
@@ -22,8 +20,6 @@ import (
2220 "code.gitea.io/gitea/modules/git"
2321 "code.gitea.io/gitea/modules/json"
2422 "code.gitea.io/gitea/modules/log"
25- "code.gitea.io/gitea/modules/markup"
26- "code.gitea.io/gitea/modules/markup/markdown"
2723 "code.gitea.io/gitea/modules/references"
2824 "code.gitea.io/gitea/modules/structs"
2925 "code.gitea.io/gitea/modules/timeutil"
@@ -687,31 +683,6 @@ func (c *Comment) LoadReview() error {
687683 return c .loadReview (db .DefaultContext )
688684}
689685
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-
715686// DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes.
716687func (c * Comment ) DiffSide () string {
717688 if c .Line < 0 {
@@ -1008,23 +979,28 @@ func GetCommentByID(ctx context.Context, id int64) (*Comment, error) {
1008979// FindCommentsOptions describes the conditions to Find comments
1009980type FindCommentsOptions struct {
1010981 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 {
1022996 cond := builder .NewCond ()
1023997 if opts .RepoID > 0 {
1024998 cond = cond .And (builder.Eq {"issue.repo_id" : opts .RepoID })
1025999 }
10261000 if opts .IssueID > 0 {
10271001 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 ))
10281004 }
10291005 if opts .ReviewID > 0 {
10301006 cond = cond .And (builder.Eq {"comment.review_id" : opts .ReviewID })
@@ -1044,13 +1020,16 @@ func (opts *FindCommentsOptions) toConds() builder.Cond {
10441020 if len (opts .TreePath ) > 0 {
10451021 cond = cond .And (builder.Eq {"comment.tree_path" : opts .TreePath })
10461022 }
1023+ if ! opts .Invalidated .IsNone () {
1024+ cond = cond .And (builder.Eq {"comment.invalidated" : opts .Invalidated .IsTrue ()})
1025+ }
10471026 return cond
10481027}
10491028
10501029// FindComments returns all comments according options
10511030func FindComments (ctx context.Context , opts * FindCommentsOptions ) ([]* Comment , error ) {
10521031 comments := make ([]* Comment , 0 , 10 )
1053- sess := db .GetEngine (ctx ).Where (opts .toConds ())
1032+ sess := db .GetEngine (ctx ).Where (opts .ToConds ())
10541033 if opts .RepoID > 0 {
10551034 sess .Join ("INNER" , "issue" , "issue.id = comment.issue_id" )
10561035 }
@@ -1069,13 +1048,19 @@ func FindComments(ctx context.Context, opts *FindCommentsOptions) ([]*Comment, e
10691048
10701049// CountComments count all comments according options by ignoring pagination
10711050func CountComments (opts * FindCommentsOptions ) (int64 , error ) {
1072- sess := db .GetEngine (db .DefaultContext ).Where (opts .toConds ())
1051+ sess := db .GetEngine (db .DefaultContext ).Where (opts .ToConds ())
10731052 if opts .RepoID > 0 {
10741053 sess .Join ("INNER" , "issue" , "issue.id = comment.issue_id" )
10751054 }
10761055 return sess .Count (& Comment {})
10771056}
10781057
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+
10791064// UpdateComment updates information of comment.
10801065func UpdateComment (c * Comment , doer * user_model.User ) error {
10811066 ctx , committer , err := db .TxContext (db .DefaultContext )
@@ -1134,120 +1119,6 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
11341119 return DeleteReaction (ctx , & ReactionOptions {CommentID : comment .ID })
11351120}
11361121
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-
12511122// UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id
12521123func UpdateCommentsMigrationsByType (tp structs.GitServiceType , originalAuthorID string , posterID int64 ) error {
12531124 _ , err := db .GetEngine (db .DefaultContext ).Table ("comment" ).
0 commit comments