You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

comments.go 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package comments
  5. import (
  6. "bytes"
  7. "fmt"
  8. "strings"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/modules/git"
  11. "code.gitea.io/gitea/modules/notification"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/services/gitdiff"
  14. )
  15. // CreateIssueComment creates a plain issue comment.
  16. func CreateIssueComment(doer *models.User, repo *models.Repository, issue *models.Issue, content string, attachments []string) (*models.Comment, error) {
  17. comment, err := models.CreateComment(&models.CreateCommentOptions{
  18. Type: models.CommentTypeComment,
  19. Doer: doer,
  20. Repo: repo,
  21. Issue: issue,
  22. Content: content,
  23. Attachments: attachments,
  24. })
  25. if err != nil {
  26. return nil, err
  27. }
  28. notification.NotifyCreateIssueComment(doer, repo, issue, comment)
  29. return comment, nil
  30. }
  31. // CreateCodeComment creates a plain code comment at the specified line / path
  32. func CreateCodeComment(doer *models.User, repo *models.Repository, issue *models.Issue, content, treePath string, line, reviewID int64) (*models.Comment, error) {
  33. var commitID, patch string
  34. pr, err := models.GetPullRequestByIssueID(issue.ID)
  35. if err != nil {
  36. return nil, fmt.Errorf("GetPullRequestByIssueID: %v", err)
  37. }
  38. if err := pr.GetBaseRepo(); err != nil {
  39. return nil, fmt.Errorf("GetHeadRepo: %v", err)
  40. }
  41. gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
  42. if err != nil {
  43. return nil, fmt.Errorf("OpenRepository: %v", err)
  44. }
  45. // FIXME validate treePath
  46. // Get latest commit referencing the commented line
  47. // No need for get commit for base branch changes
  48. if line > 0 {
  49. commit, err := gitRepo.LineBlame(pr.GetGitRefName(), gitRepo.Path, treePath, uint(line))
  50. if err == nil {
  51. commitID = commit.ID.String()
  52. } else if !strings.Contains(err.Error(), "exit status 128 - fatal: no such path") {
  53. return nil, fmt.Errorf("LineBlame[%s, %s, %s, %d]: %v", pr.GetGitRefName(), gitRepo.Path, treePath, line, err)
  54. }
  55. }
  56. // Only fetch diff if comment is review comment
  57. if reviewID != 0 {
  58. headCommitID, err := gitRepo.GetRefCommitID(pr.GetGitRefName())
  59. if err != nil {
  60. return nil, fmt.Errorf("GetRefCommitID[%s]: %v", pr.GetGitRefName(), err)
  61. }
  62. patchBuf := new(bytes.Buffer)
  63. if err := gitdiff.GetRawDiffForFile(gitRepo.Path, pr.MergeBase, headCommitID, gitdiff.RawDiffNormal, treePath, patchBuf); err != nil {
  64. return nil, fmt.Errorf("GetRawDiffForLine[%s, %s, %s, %s]: %v", err, gitRepo.Path, pr.MergeBase, headCommitID, treePath)
  65. }
  66. patch = gitdiff.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: line}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
  67. }
  68. return models.CreateComment(&models.CreateCommentOptions{
  69. Type: models.CommentTypeCode,
  70. Doer: doer,
  71. Repo: repo,
  72. Issue: issue,
  73. Content: content,
  74. LineNum: line,
  75. TreePath: treePath,
  76. CommitSHA: commitID,
  77. ReviewID: reviewID,
  78. Patch: patch,
  79. })
  80. }
  81. // UpdateComment updates information of comment.
  82. func UpdateComment(c *models.Comment, doer *models.User, oldContent string) error {
  83. if err := models.UpdateComment(c, doer); err != nil {
  84. return err
  85. }
  86. notification.NotifyUpdateComment(doer, c, oldContent)
  87. return nil
  88. }
  89. // DeleteComment deletes the comment
  90. func DeleteComment(comment *models.Comment, doer *models.User) error {
  91. if err := models.DeleteComment(comment, doer); err != nil {
  92. return err
  93. }
  94. notification.NotifyDeleteComment(doer, comment)
  95. return nil
  96. }