summaryrefslogtreecommitdiffstats
path: root/services/issue/comments.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
committerDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
commitdd136858f1ea40ad3c94191d647487fa4f31926c (patch)
tree58fec94a7b2a12510c9664b21793f1ed560c6518 /services/issue/comments.go
parentInitial commit. (diff)
downloadforgejo-dd136858f1ea40ad3c94191d647487fa4f31926c.tar.xz
forgejo-dd136858f1ea40ad3c94191d647487fa4f31926c.zip
Adding upstream version 9.0.0.HEADupstream/9.0.0upstreamdebian
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'services/issue/comments.go')
-rw-r--r--services/issue/comments.go136
1 files changed, 136 insertions, 0 deletions
diff --git a/services/issue/comments.go b/services/issue/comments.go
new file mode 100644
index 0000000..3ab577b
--- /dev/null
+++ b/services/issue/comments.go
@@ -0,0 +1,136 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package issue
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/db"
+ issues_model "code.gitea.io/gitea/models/issues"
+ repo_model "code.gitea.io/gitea/models/repo"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/timeutil"
+ notify_service "code.gitea.io/gitea/services/notify"
+)
+
+// CreateRefComment creates a commit reference comment to issue.
+func CreateRefComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error {
+ if len(commitSHA) == 0 {
+ return fmt.Errorf("cannot create reference with empty commit SHA")
+ }
+
+ // Check if same reference from same commit has already existed.
+ has, err := db.GetEngine(ctx).Get(&issues_model.Comment{
+ Type: issues_model.CommentTypeCommitRef,
+ IssueID: issue.ID,
+ CommitSHA: commitSHA,
+ })
+ if err != nil {
+ return fmt.Errorf("check reference comment: %w", err)
+ } else if has {
+ return nil
+ }
+
+ _, err = issues_model.CreateComment(ctx, &issues_model.CreateCommentOptions{
+ Type: issues_model.CommentTypeCommitRef,
+ Doer: doer,
+ Repo: repo,
+ Issue: issue,
+ CommitSHA: commitSHA,
+ Content: content,
+ })
+ return err
+}
+
+// CreateIssueComment creates a plain issue comment.
+func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) {
+ // Check if doer is blocked by the poster of the issue or by the owner of the repository.
+ if user_model.IsBlockedMultiple(ctx, []int64{issue.PosterID, repo.OwnerID}, doer.ID) {
+ return nil, user_model.ErrBlockedByUser
+ }
+
+ comment, err := issues_model.CreateComment(ctx, &issues_model.CreateCommentOptions{
+ Type: issues_model.CommentTypeComment,
+ Doer: doer,
+ Repo: repo,
+ Issue: issue,
+ Content: content,
+ Attachments: attachments,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ mentions, err := issues_model.FindAndUpdateIssueMentions(ctx, issue, doer, comment.Content)
+ if err != nil {
+ return nil, err
+ }
+
+ notify_service.CreateIssueComment(ctx, doer, repo, issue, comment, mentions)
+
+ return comment, nil
+}
+
+// UpdateComment updates information of comment.
+func UpdateComment(ctx context.Context, c *issues_model.Comment, contentVersion int, doer *user_model.User, oldContent string) error {
+ if err := c.LoadReview(ctx); err != nil {
+ return err
+ }
+ isPartOfPendingReview := c.Review != nil && c.Review.Type == issues_model.ReviewTypePending
+
+ needsContentHistory := c.Content != oldContent && c.Type.HasContentSupport() && !isPartOfPendingReview
+ if needsContentHistory {
+ hasContentHistory, err := issues_model.HasIssueContentHistory(ctx, c.IssueID, c.ID)
+ if err != nil {
+ return err
+ }
+ if !hasContentHistory {
+ if err = issues_model.SaveIssueContentHistory(ctx, c.PosterID, c.IssueID, c.ID,
+ c.CreatedUnix, oldContent, true); err != nil {
+ return err
+ }
+ }
+ }
+
+ if err := issues_model.UpdateComment(ctx, c, contentVersion, doer); err != nil {
+ return err
+ }
+
+ if needsContentHistory {
+ historyDate := timeutil.TimeStampNow()
+ if c.Issue.NoAutoTime {
+ historyDate = c.Issue.UpdatedUnix
+ }
+ err := issues_model.SaveIssueContentHistory(ctx, doer.ID, c.IssueID, c.ID, historyDate, c.Content, false)
+ if err != nil {
+ return err
+ }
+ }
+
+ if !isPartOfPendingReview {
+ notify_service.UpdateComment(ctx, doer, c, oldContent)
+ }
+
+ return nil
+}
+
+// DeleteComment deletes the comment
+func DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) error {
+ err := db.WithTx(ctx, func(ctx context.Context) error {
+ return issues_model.DeleteComment(ctx, comment)
+ })
+ if err != nil {
+ return err
+ }
+
+ if err := comment.LoadReview(ctx); err != nil {
+ return err
+ }
+ if comment.Review == nil || comment.Review.Type != issues_model.ReviewTypePending {
+ notify_service.DeleteComment(ctx, doer, comment)
+ }
+
+ return nil
+}