2018-08-06 07:43:22 +03:00
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"fmt"
2021-04-05 18:30:52 +03:00
"net/http"
2018-08-06 07:43:22 +03:00
"code.gitea.io/gitea/models"
2021-01-09 00:49:55 +03:00
"code.gitea.io/gitea/modules/base"
2018-08-06 07:43:22 +03:00
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
2021-06-15 04:12:33 +03:00
"code.gitea.io/gitea/modules/setting"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/web"
2021-04-06 22:44:05 +03:00
"code.gitea.io/gitea/services/forms"
2019-09-27 03:22:36 +03:00
pull_service "code.gitea.io/gitea/services/pull"
2018-08-06 07:43:22 +03:00
)
2021-01-09 00:49:55 +03:00
const (
tplConversation base . TplName = "repo/diff/conversation"
tplNewComment base . TplName = "repo/diff/new_comment"
)
// RenderNewCodeCommentForm will render the form for creating a new review comment
func RenderNewCodeCommentForm ( ctx * context . Context ) {
issue := GetActionIssue ( ctx )
if ! issue . IsPull {
return
}
currentReview , err := models . GetCurrentReview ( ctx . User , issue )
if err != nil && ! models . IsErrReviewNotExist ( err ) {
ctx . ServerError ( "GetCurrentReview" , err )
return
}
ctx . Data [ "PageIsPullFiles" ] = true
ctx . Data [ "Issue" ] = issue
ctx . Data [ "CurrentReview" ] = currentReview
pullHeadCommitID , err := ctx . Repo . GitRepo . GetRefCommitID ( issue . PullRequest . GetGitRefName ( ) )
if err != nil {
ctx . ServerError ( "GetRefCommitID" , err )
return
}
ctx . Data [ "AfterCommitID" ] = pullHeadCommitID
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplNewComment )
2021-01-09 00:49:55 +03:00
}
2018-08-06 07:43:22 +03:00
// CreateCodeComment will create a code comment including an pending review if required
2021-01-26 18:36:53 +03:00
func CreateCodeComment ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . CodeCommentForm )
2018-08-06 07:43:22 +03:00
issue := GetActionIssue ( ctx )
if ! issue . IsPull {
return
}
if ctx . Written ( ) {
return
}
if ctx . HasError ( ) {
ctx . Flash . Error ( ctx . Data [ "ErrorMsg" ] . ( string ) )
ctx . Redirect ( fmt . Sprintf ( "%s/pulls/%d/files" , ctx . Repo . RepoLink , issue . Index ) )
return
}
2019-11-14 05:57:36 +03:00
2018-08-06 07:43:22 +03:00
signedLine := form . Line
if form . Side == "previous" {
signedLine *= - 1
}
2019-11-14 05:57:36 +03:00
comment , err := pull_service . CreateCodeComment (
2018-08-06 07:43:22 +03:00
ctx . User ,
2020-01-09 04:47:45 +03:00
ctx . Repo . GitRepo ,
2018-08-06 07:43:22 +03:00
issue ,
2019-11-14 05:57:36 +03:00
signedLine ,
2018-08-06 07:43:22 +03:00
form . Content ,
form . TreePath ,
2019-11-14 05:57:36 +03:00
form . IsReview ,
form . Reply ,
2020-01-09 04:47:45 +03:00
form . LatestCommitID ,
2018-08-06 07:43:22 +03:00
)
if err != nil {
ctx . ServerError ( "CreateCodeComment" , err )
return
}
2020-03-30 21:52:45 +03:00
if comment == nil {
log . Trace ( "Comment not created: %-v #%d[%d]" , ctx . Repo . Repository , issue . Index , issue . ID )
2019-11-14 05:57:36 +03:00
ctx . Redirect ( fmt . Sprintf ( "%s/pulls/%d/files" , ctx . Repo . RepoLink , issue . Index ) )
2020-03-30 21:52:45 +03:00
return
2019-11-14 05:57:36 +03:00
}
2020-03-30 21:52:45 +03:00
log . Trace ( "Comment created: %-v #%d[%d] Comment[%d]" , ctx . Repo . Repository , issue . Index , issue . ID , comment . ID )
2021-01-09 00:49:55 +03:00
if form . Origin == "diff" {
renderConversation ( ctx , comment )
return
}
2020-03-30 21:52:45 +03:00
ctx . Redirect ( comment . HTMLURL ( ) )
2018-08-06 07:43:22 +03:00
}
2020-04-18 16:50:25 +03:00
// UpdateResolveConversation add or remove an Conversation resolved mark
func UpdateResolveConversation ( ctx * context . Context ) {
2021-01-09 00:49:55 +03:00
origin := ctx . Query ( "origin" )
2020-04-18 16:50:25 +03:00
action := ctx . Query ( "action" )
commentID := ctx . QueryInt64 ( "comment_id" )
comment , err := models . GetCommentByID ( commentID )
if err != nil {
ctx . ServerError ( "GetIssueByID" , err )
return
}
if err = comment . LoadIssue ( ) ; err != nil {
ctx . ServerError ( "comment.LoadIssue" , err )
return
}
var permResult bool
if permResult , err = models . CanMarkConversation ( comment . Issue , ctx . User ) ; err != nil {
ctx . ServerError ( "CanMarkConversation" , err )
return
}
if ! permResult {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusForbidden )
2020-04-18 16:50:25 +03:00
return
}
if ! comment . Issue . IsPull {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusBadRequest )
2020-04-18 16:50:25 +03:00
return
}
if action == "Resolve" || action == "UnResolve" {
err = models . MarkConversation ( comment , ctx . User , action == "Resolve" )
if err != nil {
ctx . ServerError ( "MarkConversation" , err )
return
}
} else {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusBadRequest )
2020-04-18 16:50:25 +03:00
return
}
2021-01-09 00:49:55 +03:00
if origin == "diff" {
renderConversation ( ctx , comment )
return
}
2021-04-05 18:30:52 +03:00
ctx . JSON ( http . StatusOK , map [ string ] interface { } {
2020-04-18 16:50:25 +03:00
"ok" : true ,
} )
}
2021-01-09 00:49:55 +03:00
func renderConversation ( ctx * context . Context , comment * models . Comment ) {
comments , err := models . FetchCodeCommentsByLine ( comment . Issue , ctx . User , comment . TreePath , comment . Line )
if err != nil {
ctx . ServerError ( "FetchCodeCommentsByLine" , err )
return
}
ctx . Data [ "PageIsPullFiles" ] = true
ctx . Data [ "comments" ] = comments
ctx . Data [ "CanMarkConversation" ] = true
ctx . Data [ "Issue" ] = comment . Issue
if err = comment . Issue . LoadPullRequest ( ) ; err != nil {
ctx . ServerError ( "comment.Issue.LoadPullRequest" , err )
return
}
pullHeadCommitID , err := ctx . Repo . GitRepo . GetRefCommitID ( comment . Issue . PullRequest . GetGitRefName ( ) )
if err != nil {
ctx . ServerError ( "GetRefCommitID" , err )
return
}
ctx . Data [ "AfterCommitID" ] = pullHeadCommitID
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplConversation )
2021-01-09 00:49:55 +03:00
}
2018-08-06 07:43:22 +03:00
// SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist
2021-01-26 18:36:53 +03:00
func SubmitReview ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . SubmitReviewForm )
2018-08-06 07:43:22 +03:00
issue := GetActionIssue ( ctx )
if ! issue . IsPull {
return
}
if ctx . Written ( ) {
return
}
if ctx . HasError ( ) {
ctx . Flash . Error ( ctx . Data [ "ErrorMsg" ] . ( string ) )
ctx . Redirect ( fmt . Sprintf ( "%s/pulls/%d/files" , ctx . Repo . RepoLink , issue . Index ) )
return
}
reviewType := form . ReviewType ( )
2018-08-20 08:04:01 +03:00
switch reviewType {
case models . ReviewTypeUnknown :
2019-11-14 05:57:36 +03:00
ctx . ServerError ( "ReviewType" , fmt . Errorf ( "unknown ReviewType: %s" , form . Type ) )
2018-08-06 07:43:22 +03:00
return
2018-08-20 08:04:01 +03:00
// can not approve/reject your own PR
case models . ReviewTypeApprove , models . ReviewTypeReject :
2020-01-17 13:23:46 +03:00
if issue . IsPoster ( ctx . User . ID ) {
2018-08-20 08:04:01 +03:00
var translated string
if reviewType == models . ReviewTypeApprove {
translated = ctx . Tr ( "repo.issues.review.self.approval" )
} else {
translated = ctx . Tr ( "repo.issues.review.self.rejection" )
}
ctx . Flash . Error ( translated )
ctx . Redirect ( fmt . Sprintf ( "%s/pulls/%d/files" , ctx . Repo . RepoLink , issue . Index ) )
return
}
2018-08-06 07:43:22 +03:00
}
2018-08-07 20:15:41 +03:00
2021-06-15 04:12:33 +03:00
var attachments [ ] string
if setting . Attachment . Enabled {
attachments = form . Files
}
_ , comm , err := pull_service . SubmitReview ( ctx . User , ctx . Repo . GitRepo , issue , reviewType , form . Content , form . CommitID , attachments )
2018-08-06 07:43:22 +03:00
if err != nil {
2019-11-14 05:57:36 +03:00
if models . IsContentEmptyErr ( err ) {
ctx . Flash . Error ( ctx . Tr ( "repo.issues.review.content.empty" ) )
ctx . Redirect ( fmt . Sprintf ( "%s/pulls/%d/files" , ctx . Repo . RepoLink , issue . Index ) )
} else {
ctx . ServerError ( "SubmitReview" , err )
2018-08-06 07:43:22 +03:00
}
2018-10-18 14:23:05 +03:00
return
}
2018-08-06 07:43:22 +03:00
ctx . Redirect ( fmt . Sprintf ( "%s/pulls/%d#%s" , ctx . Repo . RepoLink , issue . Index , comm . HashTag ( ) ) )
}
2021-02-11 20:32:25 +03:00
// DismissReview dismissing stale review by repo admin
func DismissReview ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . DismissReviewForm )
2021-02-11 20:32:25 +03:00
comm , err := pull_service . DismissReview ( form . ReviewID , form . Message , ctx . User , true )
if err != nil {
ctx . ServerError ( "pull_service.DismissReview" , err )
return
}
ctx . Redirect ( fmt . Sprintf ( "%s/pulls/%d#%s" , ctx . Repo . RepoLink , comm . Issue . Index , comm . HashTag ( ) ) )
}