summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/db/list_options.go50
-rw-r--r--models/issues/comment.go183
-rw-r--r--models/issues/comment_code.go129
-rw-r--r--models/issues/pull_list.go27
-rw-r--r--models/issues/review.go8
-rw-r--r--services/pull/pull.go2
-rw-r--r--services/pull/review.go49
7 files changed, 260 insertions, 188 deletions
diff --git a/models/db/list_options.go b/models/db/list_options.go
index b9ee360b1b..2456f90f3b 100644
--- a/models/db/list_options.go
+++ b/models/db/list_options.go
@@ -4,8 +4,11 @@
package db
import (
+ "context"
+
"code.gitea.io/gitea/modules/setting"
+ "xorm.io/builder"
"xorm.io/xorm"
)
@@ -18,6 +21,7 @@ const (
type Paginator interface {
GetSkipTake() (skip, take int)
GetStartEnd() (start, end int)
+ IsListAll() bool
}
// GetPaginatedSession creates a paginated database session
@@ -44,9 +48,12 @@ func SetEnginePagination(e Engine, p Paginator) Engine {
// ListOptions options to paginate results
type ListOptions struct {
PageSize int
- Page int // start from 1
+ Page int // start from 1
+ ListAll bool // if true, then PageSize and Page will not be taken
}
+var _ Paginator = &ListOptions{}
+
// GetSkipTake returns the skip and take values
func (opts *ListOptions) GetSkipTake() (skip, take int) {
opts.SetDefaultValues()
@@ -60,6 +67,11 @@ func (opts *ListOptions) GetStartEnd() (start, end int) {
return start, end
}
+// IsListAll indicates PageSize and Page will be ignored
+func (opts *ListOptions) IsListAll() bool {
+ return opts.ListAll
+}
+
// SetDefaultValues sets default values
func (opts *ListOptions) SetDefaultValues() {
if opts.PageSize <= 0 {
@@ -79,6 +91,8 @@ type AbsoluteListOptions struct {
take int
}
+var _ Paginator = &AbsoluteListOptions{}
+
// NewAbsoluteListOptions creates a list option with applied limits
func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
if skip < 0 {
@@ -93,6 +107,11 @@ func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
return &AbsoluteListOptions{skip, take}
}
+// IsListAll will always return false
+func (opts *AbsoluteListOptions) IsListAll() bool {
+ return false
+}
+
// GetSkipTake returns the skip and take values
func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
return opts.skip, opts.take
@@ -102,3 +121,32 @@ func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) {
return opts.skip, opts.skip + opts.take
}
+
+// FindOptions represents a find options
+type FindOptions interface {
+ Paginator
+ ToConds() builder.Cond
+}
+
+// Find represents a common find function which accept an options interface
+func Find[T any](ctx context.Context, opts FindOptions, objects *[]T) error {
+ sess := GetEngine(ctx).Where(opts.ToConds())
+ if !opts.IsListAll() {
+ sess.Limit(opts.GetSkipTake())
+ }
+ return sess.Find(&objects)
+}
+
+// Count represents a common count function which accept an options interface
+func Count[T any](ctx context.Context, opts FindOptions, object T) (int64, error) {
+ return GetEngine(ctx).Where(opts.ToConds()).Count(object)
+}
+
+// FindAndCount represents a common findandcount function which accept an options interface
+func FindAndCount[T any](ctx context.Context, opts FindOptions, objects *[]T) (int64, error) {
+ sess := GetEngine(ctx).Where(opts.ToConds())
+ if !opts.IsListAll() {
+ sess.Limit(opts.GetSkipTake())
+ }
+ return sess.FindAndCount(&objects)
+}
diff --git a/models/issues/comment.go b/models/issues/comment.go
index 2dcbc7d819..87e6b0a229 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -8,9 +8,7 @@ package issues
import (
"context"
"fmt"
- "regexp"
"strconv"
- "strings"
"unicode/utf8"
"code.gitea.io/gitea/models/db"
@@ -22,8 +20,6 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/markup"
- "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
@@ -687,31 +683,6 @@ func (c *Comment) LoadReview() error {
return c.loadReview(db.DefaultContext)
}
-var notEnoughLines = regexp.MustCompile(`fatal: file .* has only \d+ lines?`)
-
-func (c *Comment) checkInvalidation(doer *user_model.User, repo *git.Repository, branch string) error {
- // FIXME differentiate between previous and proposed line
- commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine()))
- if err != nil && (strings.Contains(err.Error(), "fatal: no such path") || notEnoughLines.MatchString(err.Error())) {
- c.Invalidated = true
- return UpdateComment(c, doer)
- }
- if err != nil {
- return err
- }
- if c.CommitSHA != "" && c.CommitSHA != commit.ID.String() {
- c.Invalidated = true
- return UpdateComment(c, doer)
- }
- return nil
-}
-
-// CheckInvalidation checks if the line of code comment got changed by another commit.
-// If the line got changed the comment is going to be invalidated.
-func (c *Comment) CheckInvalidation(repo *git.Repository, doer *user_model.User, branch string) error {
- return c.checkInvalidation(doer, repo, branch)
-}
-
// DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes.
func (c *Comment) DiffSide() string {
if c.Line < 0 {
@@ -1008,23 +979,28 @@ func GetCommentByID(ctx context.Context, id int64) (*Comment, error) {
// FindCommentsOptions describes the conditions to Find comments
type FindCommentsOptions struct {
db.ListOptions
- RepoID int64
- IssueID int64
- ReviewID int64
- Since int64
- Before int64
- Line int64
- TreePath string
- Type CommentType
-}
-
-func (opts *FindCommentsOptions) toConds() builder.Cond {
+ RepoID int64
+ IssueID int64
+ ReviewID int64
+ Since int64
+ Before int64
+ Line int64
+ TreePath string
+ Type CommentType
+ IssueIDs []int64
+ Invalidated util.OptionalBool
+}
+
+// ToConds implements FindOptions interface
+func (opts *FindCommentsOptions) ToConds() builder.Cond {
cond := builder.NewCond()
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"issue.repo_id": opts.RepoID})
}
if opts.IssueID > 0 {
cond = cond.And(builder.Eq{"comment.issue_id": opts.IssueID})
+ } else if len(opts.IssueIDs) > 0 {
+ cond = cond.And(builder.In("comment.issue_id", opts.IssueIDs))
}
if opts.ReviewID > 0 {
cond = cond.And(builder.Eq{"comment.review_id": opts.ReviewID})
@@ -1044,13 +1020,16 @@ func (opts *FindCommentsOptions) toConds() builder.Cond {
if len(opts.TreePath) > 0 {
cond = cond.And(builder.Eq{"comment.tree_path": opts.TreePath})
}
+ if !opts.Invalidated.IsNone() {
+ cond = cond.And(builder.Eq{"comment.invalidated": opts.Invalidated.IsTrue()})
+ }
return cond
}
// FindComments returns all comments according options
func FindComments(ctx context.Context, opts *FindCommentsOptions) ([]*Comment, error) {
comments := make([]*Comment, 0, 10)
- sess := db.GetEngine(ctx).Where(opts.toConds())
+ sess := db.GetEngine(ctx).Where(opts.ToConds())
if opts.RepoID > 0 {
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
}
@@ -1069,13 +1048,19 @@ func FindComments(ctx context.Context, opts *FindCommentsOptions) ([]*Comment, e
// CountComments count all comments according options by ignoring pagination
func CountComments(opts *FindCommentsOptions) (int64, error) {
- sess := db.GetEngine(db.DefaultContext).Where(opts.toConds())
+ sess := db.GetEngine(db.DefaultContext).Where(opts.ToConds())
if opts.RepoID > 0 {
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
}
return sess.Count(&Comment{})
}
+// UpdateCommentInvalidate updates comment invalidated column
+func UpdateCommentInvalidate(ctx context.Context, c *Comment) error {
+ _, err := db.GetEngine(ctx).ID(c.ID).Cols("invalidated").Update(c)
+ return err
+}
+
// UpdateComment updates information of comment.
func UpdateComment(c *Comment, doer *user_model.User) error {
ctx, committer, err := db.TxContext(db.DefaultContext)
@@ -1134,120 +1119,6 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
return DeleteReaction(ctx, &ReactionOptions{CommentID: comment.ID})
}
-// 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
-func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User) (CodeComments, error) {
- return fetchCodeCommentsByReview(ctx, issue, currentUser, nil)
-}
-
-func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review) (CodeComments, error) {
- pathToLineToComment := make(CodeComments)
- if review == nil {
- review = &Review{ID: 0}
- }
- opts := FindCommentsOptions{
- Type: CommentTypeCode,
- IssueID: issue.ID,
- ReviewID: review.ID,
- }
-
- comments, err := findCodeComments(ctx, opts, issue, currentUser, review)
- 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
-}
-
-func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review) ([]*Comment, error) {
- var comments []*Comment
- if review == nil {
- review = &Review{ID: 0}
- }
- conds := opts.toConds()
- if review.ID == 0 {
- conds = conds.And(builder.Eq{"invalidated": false})
- }
- 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
- }
-
- if err := CommentList(comments).LoadPosters(ctx); err != nil {
- 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++
-
- if err := comment.LoadResolveDoer(); err != nil {
- return nil, err
- }
-
- if err := comment.LoadReactions(issue.Repo); err != nil {
- return nil, err
- }
-
- var err error
- if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
- Ctx: ctx,
- URLPrefix: issue.Repo.Link(),
- Metas: issue.Repo.ComposeMetas(),
- }, comment.Content); err != nil {
- return nil, err
- }
- }
- return comments[:n], nil
-}
-
-// FetchCodeCommentsByLine fetches the code comments for a given treePath and line number
-func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) {
- opts := FindCommentsOptions{
- Type: CommentTypeCode,
- IssueID: issue.ID,
- TreePath: treePath,
- Line: line,
- }
- return findCodeComments(ctx, opts, issue, currentUser, nil)
-}
-
// UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id
func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID string, posterID int64) error {
_, err := db.GetEngine(db.DefaultContext).Table("comment").
diff --git a/models/issues/comment_code.go b/models/issues/comment_code.go
new file mode 100644
index 0000000000..8475da1a8c
--- /dev/null
+++ b/models/issues/comment_code.go
@@ -0,0 +1,129 @@
+// 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
+func FetchCodeComments(ctx context.Context, issue *Issue, currentUser *user_model.User) (CodeComments, error) {
+ return fetchCodeCommentsByReview(ctx, issue, currentUser, nil)
+}
+
+func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *user_model.User, review *Review) (CodeComments, error) {
+ pathToLineToComment := make(CodeComments)
+ if review == nil {
+ review = &Review{ID: 0}
+ }
+ opts := FindCommentsOptions{
+ Type: CommentTypeCode,
+ IssueID: issue.ID,
+ ReviewID: review.ID,
+ }
+
+ comments, err := findCodeComments(ctx, opts, issue, currentUser, review)
+ 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
+}
+
+func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review) ([]*Comment, error) {
+ var comments []*Comment
+ if review == nil {
+ review = &Review{ID: 0}
+ }
+ conds := opts.ToConds()
+ if review.ID == 0 {
+ conds = conds.And(builder.Eq{"invalidated": false})
+ }
+ 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
+ }
+
+ if err := CommentList(comments).LoadPosters(ctx); err != nil {
+ 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++
+
+ if err := comment.LoadResolveDoer(); err != nil {
+ return nil, err
+ }
+
+ if err := comment.LoadReactions(issue.Repo); err != nil {
+ return nil, err
+ }
+
+ var err error
+ if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
+ Ctx: ctx,
+ URLPrefix: issue.Repo.Link(),
+ Metas: issue.Repo.ComposeMetas(),
+ }, comment.Content); err != nil {
+ return nil, err
+ }
+ }
+ return comments[:n], nil
+}
+
+// FetchCodeCommentsByLine fetches the code comments for a given treePath and line number
+func FetchCodeCommentsByLine(ctx context.Context, issue *Issue, currentUser *user_model.User, treePath string, line int64) ([]*Comment, error) {
+ opts := FindCommentsOptions{
+ Type: CommentTypeCode,
+ IssueID: issue.ID,
+ TreePath: treePath,
+ Line: line,
+ }
+ return findCodeComments(ctx, opts, issue, currentUser, nil)
+}
diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go
index 432e848e97..12dbff107d 100644
--- a/models/issues/pull_list.go
+++ b/models/issues/pull_list.go
@@ -12,7 +12,6 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"xorm.io/xorm"
@@ -161,7 +160,7 @@ func (prs PullRequestList) loadAttributes(ctx context.Context) error {
}
// Load issues.
- issueIDs := prs.getIssueIDs()
+ issueIDs := prs.GetIssueIDs()
issues := make([]*Issue, 0, len(issueIDs))
if err := db.GetEngine(ctx).
Where("id > 0").
@@ -180,7 +179,8 @@ func (prs PullRequestList) loadAttributes(ctx context.Context) error {
return nil
}
-func (prs PullRequestList) getIssueIDs() []int64 {
+// GetIssueIDs returns all issue ids
+func (prs PullRequestList) GetIssueIDs() []int64 {
issueIDs := make([]int64, 0, len(prs))
for i := range prs {
issueIDs = append(issueIDs, prs[i].IssueID)
@@ -192,24 +192,3 @@ func (prs PullRequestList) getIssueIDs() []int64 {
func (prs PullRequestList) LoadAttributes() error {
return prs.loadAttributes(db.DefaultContext)
}
-
-// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change
-func (prs PullRequestList) InvalidateCodeComments(ctx context.Context, doer *user_model.User, repo *git.Repository, branch string) error {
- if len(prs) == 0 {
- return nil
- }
- issueIDs := prs.getIssueIDs()
- var codeComments []*Comment
- if err := db.GetEngine(ctx).
- Where("type = ? and invalidated = ?", CommentTypeCode, false).
- In("issue_id", issueIDs).
- Find(&codeComments); err != nil {
- return fmt.Errorf("find code comments: %w", err)
- }
- for _, comment := range codeComments {
- if err := comment.CheckInvalidation(repo, doer, branch); err != nil {
- return err
- }
- }
- return nil
-}
diff --git a/models/issues/review.go b/models/issues/review.go
index d8e517ad3c..7e1a39bb5b 100644
--- a/models/issues/review.go
+++ b/models/issues/review.go
@@ -972,7 +972,7 @@ func DeleteReview(r *Review) error {
ReviewID: r.ID,
}
- if _, err := sess.Where(opts.toConds()).Delete(new(Comment)); err != nil {
+ if _, err := sess.Where(opts.ToConds()).Delete(new(Comment)); err != nil {
return err
}
@@ -982,7 +982,7 @@ func DeleteReview(r *Review) error {
ReviewID: r.ID,
}
- if _, err := sess.Where(opts.toConds()).Delete(new(Comment)); err != nil {
+ if _, err := sess.Where(opts.ToConds()).Delete(new(Comment)); err != nil {
return err
}
@@ -1006,7 +1006,7 @@ func (r *Review) GetCodeCommentsCount() int {
IssueID: r.IssueID,
ReviewID: r.ID,
}
- conds := opts.toConds()
+ conds := opts.ToConds()
if r.ID == 0 {
conds = conds.And(builder.Eq{"invalidated": false})
}
@@ -1026,7 +1026,7 @@ func (r *Review) HTMLURL() string {
ReviewID: r.ID,
}
comment := new(Comment)
- has, err := db.GetEngine(db.DefaultContext).Where(opts.toConds()).Get(comment)
+ has, err := db.GetEngine(db.DefaultContext).Where(opts.ToConds()).Get(comment)
if err != nil || !has {
return ""
}
diff --git a/services/pull/pull.go b/services/pull/pull.go
index afb0fa2442..08f70a5e4e 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -240,7 +240,7 @@ func checkForInvalidation(ctx context.Context, requests issues_model.PullRequest
}
go func() {
// FIXME: graceful: We need to tell the manager we're doing something...
- err := requests.InvalidateCodeComments(ctx, doer, gitRepo, branch)
+ err := InvalidateCodeComments(ctx, requests, doer, gitRepo, branch)
if err != nil {
log.Error("PullRequestList.InvalidateCodeComments: %v", err)
}
diff --git a/services/pull/review.go b/services/pull/review.go
index 67a10d7aad..ca386ca6b0 100644
--- a/services/pull/review.go
+++ b/services/pull/review.go
@@ -23,6 +23,53 @@ import (
issue_service "code.gitea.io/gitea/services/issue"
)
+var notEnoughLines = regexp.MustCompile(`fatal: file .* has only \d+ lines?`)
+
+// checkInvalidation checks if the line of code comment got changed by another commit.
+// If the line got changed the comment is going to be invalidated.
+func checkInvalidation(ctx context.Context, c *issues_model.Comment, doer *user_model.User, repo *git.Repository, branch string) error {
+ // FIXME differentiate between previous and proposed line
+ commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine()))
+ if err != nil && (strings.Contains(err.Error(), "fatal: no such path") || notEnoughLines.MatchString(err.Error())) {
+ c.Invalidated = true
+ return issues_model.UpdateCommentInvalidate(ctx, c)
+ }
+ if err != nil {
+ return err
+ }
+ if c.CommitSHA != "" && c.CommitSHA != commit.ID.String() {
+ c.Invalidated = true
+ return issues_model.UpdateCommentInvalidate(ctx, c)
+ }
+ return nil
+}
+
+// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change
+func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestList, doer *user_model.User, repo *git.Repository, branch string) error {
+ if len(prs) == 0 {
+ return nil
+ }
+ issueIDs := prs.GetIssueIDs()
+ var codeComments []*issues_model.Comment
+
+ if err := db.Find(ctx, &issues_model.FindCommentsOptions{
+ ListOptions: db.ListOptions{
+ ListAll: true,
+ },
+ Type: issues_model.CommentTypeCode,
+ Invalidated: util.OptionalBoolFalse,
+ IssueIDs: issueIDs,
+ }, &codeComments); err != nil {
+ return fmt.Errorf("find code comments: %v", err)
+ }
+ for _, comment := range codeComments {
+ if err := checkInvalidation(ctx, comment, doer, repo, branch); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// CreateCodeComment creates a comment on the code line
func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue, line int64, content, treePath string, isReview bool, replyReviewID int64, latestCommitID string) (*issues_model.Comment, error) {
var (
@@ -114,8 +161,6 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.
return comment, nil
}
-var notEnoughLines = regexp.MustCompile(`exit status 128 - fatal: file .* has only \d+ lines?`)
-
// createCodeComment creates a plain code comment at the specified line / path
func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, treePath string, line, reviewID int64) (*issues_model.Comment, error) {
var commitID, patch string