Skip to content

Commit fbe67c0

Browse files
committed
some refactor about code comments
1 parent 112e425 commit fbe67c0

File tree

7 files changed

+261
-188
lines changed

7 files changed

+261
-188
lines changed

models/db/list_options.go

+49-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
package db
55

66
import (
7+
"context"
8+
79
"code.gitea.io/gitea/modules/setting"
810

11+
"xorm.io/builder"
912
"xorm.io/xorm"
1013
)
1114

@@ -18,6 +21,7 @@ const (
1821
type Paginator interface {
1922
GetSkipTake() (skip, take int)
2023
GetStartEnd() (start, end int)
24+
IsListAll() bool
2125
}
2226

2327
// GetPaginatedSession creates a paginated database session
@@ -44,9 +48,12 @@ func SetEnginePagination(e Engine, p Paginator) Engine {
4448
// ListOptions options to paginate results
4549
type ListOptions struct {
4650
PageSize int
47-
Page int // start from 1
51+
Page int // start from 1
52+
ListAll bool // if true, then PageSize and Page will not be taken
4853
}
4954

55+
var _ Paginator = &ListOptions{}
56+
5057
// GetSkipTake returns the skip and take values
5158
func (opts *ListOptions) GetSkipTake() (skip, take int) {
5259
opts.SetDefaultValues()
@@ -60,6 +67,11 @@ func (opts *ListOptions) GetStartEnd() (start, end int) {
6067
return start, end
6168
}
6269

70+
// IsListAll indicates PageSize and Page will be ignored
71+
func (opts *ListOptions) IsListAll() bool {
72+
return opts.ListAll
73+
}
74+
6375
// SetDefaultValues sets default values
6476
func (opts *ListOptions) SetDefaultValues() {
6577
if opts.PageSize <= 0 {
@@ -79,6 +91,8 @@ type AbsoluteListOptions struct {
7991
take int
8092
}
8193

94+
var _ Paginator = &AbsoluteListOptions{}
95+
8296
// NewAbsoluteListOptions creates a list option with applied limits
8397
func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
8498
if skip < 0 {
@@ -93,6 +107,11 @@ func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
93107
return &AbsoluteListOptions{skip, take}
94108
}
95109

110+
// IsListAll will always return false
111+
func (opts *AbsoluteListOptions) IsListAll() bool {
112+
return false
113+
}
114+
96115
// GetSkipTake returns the skip and take values
97116
func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
98117
return opts.skip, opts.take
@@ -102,3 +121,32 @@ func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
102121
func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) {
103122
return opts.skip, opts.skip + opts.take
104123
}
124+
125+
// FindOptions represents a find options
126+
type FindOptions interface {
127+
Paginator
128+
ToConds() builder.Cond
129+
}
130+
131+
// Find represents a common find function which accept an options interface
132+
func Find[T any](ctx context.Context, opts FindOptions, objects *[]T) error {
133+
sess := GetEngine(ctx).Where(opts.ToConds())
134+
if !opts.IsListAll() {
135+
sess.Limit(opts.GetSkipTake())
136+
}
137+
return sess.Find(&objects)
138+
}
139+
140+
// Count represents a common count function which accept an options interface
141+
func Count[T any](ctx context.Context, opts FindOptions, object T) (int64, error) {
142+
return GetEngine(ctx).Where(opts.ToConds()).Count(object)
143+
}
144+
145+
// FindAndCount represents a common findandcount function which accept an options interface
146+
func FindAndCount[T any](ctx context.Context, opts FindOptions, objects *[]T) (int64, error) {
147+
sess := GetEngine(ctx).Where(opts.ToConds())
148+
if !opts.IsListAll() {
149+
sess.Limit(opts.GetSkipTake())
150+
}
151+
return sess.FindAndCount(&objects)
152+
}

models/issues/comment.go

+27-156
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ package issues
88
import (
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.
716687
func (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
1009980
type 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
10511030
func 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
10711050
func 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.
10801065
func 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
12521123
func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID string, posterID int64) error {
12531124
_, err := db.GetEngine(db.DefaultContext).Table("comment").

0 commit comments

Comments
 (0)