// 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" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" pull_service "code.gitea.io/gitea/services/pull" ) // CreateCodeComment will create a code comment including an pending review if required func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) { 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 } signedLine := form.Line if form.Side == "previous" { signedLine *= -1 } comment, err := pull_service.CreateCodeComment( ctx.User, ctx.Repo.GitRepo, issue, signedLine, form.Content, form.TreePath, form.IsReview, form.Reply, form.LatestCommitID, ) if err != nil { ctx.ServerError("CreateCodeComment", err) return } if comment == nil { log.Trace("Comment not created: %-v #%d[%d]", ctx.Repo.Repository, issue.Index, issue.ID) ctx.Redirect(fmt.Sprintf("%s/pulls/%d/files", ctx.Repo.RepoLink, issue.Index)) return } log.Trace("Comment created: %-v #%d[%d] Comment[%d]", ctx.Repo.Repository, issue.Index, issue.ID, comment.ID) ctx.Redirect(comment.HTMLURL()) } // UpdateResolveConversation add or remove an Conversation resolved mark func UpdateResolveConversation(ctx *context.Context) { 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 { ctx.Error(403) return } if !comment.Issue.IsPull { ctx.Error(400) return } if action == "Resolve" || action == "UnResolve" { err = models.MarkConversation(comment, ctx.User, action == "Resolve") if err != nil { ctx.ServerError("MarkConversation", err) return } } else { ctx.Error(400) return } ctx.JSON(200, map[string]interface{}{ "ok": true, }) } // SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist func SubmitReview(ctx *context.Context, form auth.SubmitReviewForm) { 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() switch reviewType { case models.ReviewTypeUnknown: ctx.ServerError("ReviewType", fmt.Errorf("unknown ReviewType: %s", form.Type)) return // can not approve/reject your own PR case models.ReviewTypeApprove, models.ReviewTypeReject: if issue.IsPoster(ctx.User.ID) { 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 } } _, comm, err := pull_service.SubmitReview(ctx.User, ctx.Repo.GitRepo, issue, reviewType, form.Content, form.CommitID) if err != nil { 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) } return } ctx.Redirect(fmt.Sprintf("%s/pulls/%d#%s", ctx.Repo.RepoLink, issue.Index, comm.HashTag())) }