2023-01-18 00:03:44 +03:00
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package issues
import (
"context"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"xorm.io/builder"
)
// CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS
type CodeComments map [ string ] map [ int64 ] [ ] * Comment
// FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line
2023-06-21 19:08:12 +03:00
func FetchCodeComments ( ctx context . Context , issue * Issue , currentUser * user_model . User , showOutdatedComments bool ) ( CodeComments , error ) {
return fetchCodeCommentsByReview ( ctx , issue , currentUser , nil , showOutdatedComments )
2023-01-18 00:03:44 +03:00
}
2023-06-21 19:08:12 +03:00
func fetchCodeCommentsByReview ( ctx context . Context , issue * Issue , currentUser * user_model . User , review * Review , showOutdatedComments bool ) ( CodeComments , error ) {
2023-01-18 00:03:44 +03:00
pathToLineToComment := make ( CodeComments )
if review == nil {
review = & Review { ID : 0 }
}
opts := FindCommentsOptions {
Type : CommentTypeCode ,
IssueID : issue . ID ,
ReviewID : review . ID ,
}
2023-06-21 19:08:12 +03:00
comments , err := findCodeComments ( ctx , opts , issue , currentUser , review , showOutdatedComments )
2023-01-18 00:03:44 +03:00
if err != nil {
return nil , err
}
for _ , comment := range comments {
if pathToLineToComment [ comment . TreePath ] == nil {
pathToLineToComment [ comment . TreePath ] = make ( map [ int64 ] [ ] * Comment )
}
pathToLineToComment [ comment . TreePath ] [ comment . Line ] = append ( pathToLineToComment [ comment . TreePath ] [ comment . Line ] , comment )
}
return pathToLineToComment , nil
}
2023-06-21 19:08:12 +03:00
func findCodeComments ( ctx context . Context , opts FindCommentsOptions , issue * Issue , currentUser * user_model . User , review * Review , showOutdatedComments bool ) ( [ ] * Comment , error ) {
2023-05-21 15:48:28 +03:00
var comments CommentList
2023-01-18 00:03:44 +03:00
if review == nil {
review = & Review { ID : 0 }
}
conds := opts . ToConds ( )
2023-06-21 19:08:12 +03:00
if ! showOutdatedComments && review . ID == 0 {
2023-01-18 00:03:44 +03:00
conds = conds . And ( builder . Eq { "invalidated" : false } )
}
2023-06-21 19:08:12 +03:00
2023-01-18 00:03:44 +03:00
e := db . GetEngine ( ctx )
if err := e . Where ( conds ) .
Asc ( "comment.created_unix" ) .
Asc ( "comment.id" ) .
Find ( & comments ) ; err != nil {
return nil , err
}
if err := issue . LoadRepo ( ctx ) ; err != nil {
return nil , err
}
2023-05-21 15:48:28 +03:00
if err := comments . LoadPosters ( ctx ) ; err != nil {
2023-01-18 00:03:44 +03:00
return nil , err
}
// Find all reviews by ReviewID
reviews := make ( map [ int64 ] * Review )
ids := make ( [ ] int64 , 0 , len ( comments ) )
for _ , comment := range comments {
if comment . ReviewID != 0 {
ids = append ( ids , comment . ReviewID )
}
}
if err := e . In ( "id" , ids ) . Find ( & reviews ) ; err != nil {
return nil , err
}
n := 0
for _ , comment := range comments {
if re , ok := reviews [ comment . ReviewID ] ; ok && re != nil {
// If the review is pending only the author can see the comments (except if the review is set)
if review . ID == 0 && re . Type == ReviewTypePending &&
( currentUser == nil || currentUser . ID != re . ReviewerID ) {
continue
}
comment . Review = re
}
comments [ n ] = comment
n ++
2023-09-29 15:12:54 +03:00
if err := comment . LoadResolveDoer ( ctx ) ; err != nil {
2023-01-18 00:03:44 +03:00
return nil , err
}
2023-09-29 15:12:54 +03:00
if err := comment . LoadReactions ( ctx , issue . Repo ) ; err != nil {
2023-01-18 00:03:44 +03:00
return nil , err
}
var err error
if comment . RenderedContent , err = markdown . RenderString ( & markup . RenderContext {
2024-01-15 11:49:24 +03:00
Ctx : ctx ,
Links : markup . Links {
Base : issue . Repo . Link ( ) ,
} ,
Metas : issue . Repo . ComposeMetas ( ctx ) ,
2023-01-18 00:03:44 +03:00
} , comment . Content ) ; err != nil {
return nil , err
}
}
return comments [ : n ] , nil
}
// FetchCodeCommentsByLine fetches the code comments for a given treePath and line number
2023-06-21 19:08:12 +03:00
func FetchCodeCommentsByLine ( ctx context . Context , issue * Issue , currentUser * user_model . User , treePath string , line int64 , showOutdatedComments bool ) ( [ ] * Comment , error ) {
2023-01-18 00:03:44 +03:00
opts := FindCommentsOptions {
Type : CommentTypeCode ,
IssueID : issue . ID ,
TreePath : treePath ,
Line : line ,
}
2023-06-21 19:08:12 +03:00
return findCodeComments ( ctx , opts , issue , currentUser , nil , showOutdatedComments )
2023-01-18 00:03:44 +03:00
}