code.gitea.io/gitea@v1.21.7/models/issues/comment_code.go (about) 1 // Copyright 2022 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package issues 5 6 import ( 7 "context" 8 9 "code.gitea.io/gitea/models/db" 10 user_model "code.gitea.io/gitea/models/user" 11 "code.gitea.io/gitea/modules/markup" 12 "code.gitea.io/gitea/modules/markup/markdown" 13 14 "xorm.io/builder" 15 ) 16 17 // CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS 18 type CodeComments map[string]map[int64][]*Comment 19 20 // FetchCodeComments will return a 2d-map: ["Path"]["Line"] = Comments at line 21 func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User, showOutdatedComments bool) (CodeComments, error) { 22 return fetchCodeCommentsByReview(ctx, issue, currentUser, nil, showOutdatedComments) 23 } 24 25 func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool) (CodeComments, error) { 26 pathToLineToComment := make(CodeComments) 27 if review == nil { 28 review = &Review{ID: 0} 29 } 30 opts := FindCommentsOptions{ 31 Type: CommentTypeCode, 32 IssueID: issue.ID, 33 ReviewID: review.ID, 34 } 35 36 comments, err := findCodeComments(ctx, opts, issue, currentUser, review, showOutdatedComments) 37 if err != nil { 38 return nil, err 39 } 40 41 for _, comment := range comments { 42 if pathToLineToComment[comment.TreePath] == nil { 43 pathToLineToComment[comment.TreePath] = make(map[int64][]*Comment) 44 } 45 pathToLineToComment[comment.TreePath][comment.Line] = append(pathToLineToComment[comment.TreePath][comment.Line], comment) 46 } 47 return pathToLineToComment, nil 48 } 49 50 func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review, showOutdatedComments bool) ([]*Comment, error) { 51 var comments CommentList 52 if review == nil { 53 review = &Review{ID: 0} 54 } 55 conds := opts.ToConds() 56 57 if !showOutdatedComments && review.ID == 0 { 58 conds = conds.And(builder.Eq{"invalidated": false}) 59 } 60 61 e := db.GetEngine(ctx) 62 if err := e.Where(conds). 63 Asc("comment.created_unix"). 64 Asc("comment.id"). 65 Find(&comments); err != nil { 66 return nil, err 67 } 68 69 if err := issue.LoadRepo(ctx); err != nil { 70 return nil, err 71 } 72 73 if err := comments.LoadPosters(ctx); err != nil { 74 return nil, err 75 } 76 77 // Find all reviews by ReviewID 78 reviews := make(map[int64]*Review) 79 ids := make([]int64, 0, len(comments)) 80 for _, comment := range comments { 81 if comment.ReviewID != 0 { 82 ids = append(ids, comment.ReviewID) 83 } 84 } 85 if err := e.In("id", ids).Find(&reviews); err != nil { 86 return nil, err 87 } 88 89 n := 0 90 for _, comment := range comments { 91 if re, ok := reviews[comment.ReviewID]; ok && re != nil { 92 // If the review is pending only the author can see the comments (except if the review is set) 93 if review.ID == 0 && re.Type == ReviewTypePending && 94 (currentUser == nil || currentUser.ID != re.ReviewerID) { 95 continue 96 } 97 comment.Review = re 98 } 99 comments[n] = comment 100 n++ 101 102 if err := comment.LoadResolveDoer(ctx); err != nil { 103 return nil, err 104 } 105 106 if err := comment.LoadReactions(ctx, issue.Repo); err != nil { 107 return nil, err 108 } 109 110 var err error 111 if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ 112 Ctx: ctx, 113 Links: markup.Links{ 114 Base: issue.Repo.Link(), 115 }, 116 Metas: issue.Repo.ComposeMetas(), 117 }, comment.Content); err != nil { 118 return nil, err 119 } 120 } 121 return comments[:n], nil 122 } 123 124 // FetchCodeCommentsByLine fetches the code comments for a given treePath and line number 125 func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64, showOutdatedComments bool) ([]*Comment, error) { 126 opts := FindCommentsOptions{ 127 Type: CommentTypeCode, 128 IssueID: issue.ID, 129 TreePath: treePath, 130 Line: line, 131 } 132 return findCodeComments(ctx, opts, issue, currentUser, nil, showOutdatedComments) 133 }