mirror of
https://github.com/go-gitea/gitea
synced 2025-09-15 13:18:13 +00:00
Use db.WithTx/WithTx2 instead of TxContext when possible (#35130)
This commit is contained in:
@@ -334,54 +334,51 @@ func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organizatio
|
||||
|
||||
// CreateReview creates a new review based on opts
|
||||
func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer committer.Close()
|
||||
sess := db.GetEngine(ctx)
|
||||
return db.WithTx2(ctx, func(ctx context.Context) (*Review, error) {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
review := &Review{
|
||||
Issue: opts.Issue,
|
||||
IssueID: opts.Issue.ID,
|
||||
Reviewer: opts.Reviewer,
|
||||
ReviewerTeam: opts.ReviewerTeam,
|
||||
Content: opts.Content,
|
||||
Official: opts.Official,
|
||||
CommitID: opts.CommitID,
|
||||
Stale: opts.Stale,
|
||||
}
|
||||
|
||||
if opts.Reviewer != nil {
|
||||
review.Type = opts.Type
|
||||
review.ReviewerID = opts.Reviewer.ID
|
||||
|
||||
reviewCond := builder.Eq{"reviewer_id": opts.Reviewer.ID, "issue_id": opts.Issue.ID}
|
||||
// make sure user review requests are cleared
|
||||
if opts.Type != ReviewTypePending {
|
||||
if _, err := sess.Where(reviewCond.And(builder.Eq{"type": ReviewTypeRequest})).Delete(new(Review)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
review := &Review{
|
||||
Issue: opts.Issue,
|
||||
IssueID: opts.Issue.ID,
|
||||
Reviewer: opts.Reviewer,
|
||||
ReviewerTeam: opts.ReviewerTeam,
|
||||
Content: opts.Content,
|
||||
Official: opts.Official,
|
||||
CommitID: opts.CommitID,
|
||||
Stale: opts.Stale,
|
||||
}
|
||||
// make sure if the created review gets dismissed no old review surface
|
||||
// other types can be ignored, as they don't affect branch protection
|
||||
if opts.Type == ReviewTypeApprove || opts.Type == ReviewTypeReject {
|
||||
if _, err := sess.Where(reviewCond.And(builder.In("type", ReviewTypeApprove, ReviewTypeReject))).
|
||||
Cols("dismissed").Update(&Review{Dismissed: true}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else if opts.ReviewerTeam != nil {
|
||||
review.Type = ReviewTypeRequest
|
||||
review.ReviewerTeamID = opts.ReviewerTeam.ID
|
||||
} else {
|
||||
return nil, errors.New("provide either reviewer or reviewer team")
|
||||
}
|
||||
|
||||
if _, err := sess.Insert(review); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return review, committer.Commit()
|
||||
if opts.Reviewer != nil {
|
||||
review.Type = opts.Type
|
||||
review.ReviewerID = opts.Reviewer.ID
|
||||
|
||||
reviewCond := builder.Eq{"reviewer_id": opts.Reviewer.ID, "issue_id": opts.Issue.ID}
|
||||
// make sure user review requests are cleared
|
||||
if opts.Type != ReviewTypePending {
|
||||
if _, err := sess.Where(reviewCond.And(builder.Eq{"type": ReviewTypeRequest})).Delete(new(Review)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// make sure if the created review gets dismissed no old review surface
|
||||
// other types can be ignored, as they don't affect branch protection
|
||||
if opts.Type == ReviewTypeApprove || opts.Type == ReviewTypeReject {
|
||||
if _, err := sess.Where(reviewCond.And(builder.In("type", ReviewTypeApprove, ReviewTypeReject))).
|
||||
Cols("dismissed").Update(&Review{Dismissed: true}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else if opts.ReviewerTeam != nil {
|
||||
review.Type = ReviewTypeRequest
|
||||
review.ReviewerTeamID = opts.ReviewerTeam.ID
|
||||
} else {
|
||||
return nil, errors.New("provide either reviewer or reviewer team")
|
||||
}
|
||||
|
||||
if _, err := sess.Insert(review); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return review, nil
|
||||
})
|
||||
}
|
||||
|
||||
// GetCurrentReview returns the current pending review of reviewer for given issue
|
||||
@@ -605,168 +602,152 @@ func DismissReview(ctx context.Context, review *Review, isDismiss bool) (err err
|
||||
|
||||
// InsertReviews inserts review and review comments
|
||||
func InsertReviews(ctx context.Context, reviews []*Review) error {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
sess := db.GetEngine(ctx)
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
for _, review := range reviews {
|
||||
if _, err := sess.NoAutoTime().Insert(review); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, review := range reviews {
|
||||
if _, err := sess.NoAutoTime().Insert(review); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := sess.NoAutoTime().Insert(&Comment{
|
||||
Type: CommentTypeReview,
|
||||
Content: review.Content,
|
||||
PosterID: review.ReviewerID,
|
||||
OriginalAuthor: review.OriginalAuthor,
|
||||
OriginalAuthorID: review.OriginalAuthorID,
|
||||
IssueID: review.IssueID,
|
||||
ReviewID: review.ID,
|
||||
CreatedUnix: review.CreatedUnix,
|
||||
UpdatedUnix: review.UpdatedUnix,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := sess.NoAutoTime().Insert(&Comment{
|
||||
Type: CommentTypeReview,
|
||||
Content: review.Content,
|
||||
PosterID: review.ReviewerID,
|
||||
OriginalAuthor: review.OriginalAuthor,
|
||||
OriginalAuthorID: review.OriginalAuthorID,
|
||||
IssueID: review.IssueID,
|
||||
ReviewID: review.ID,
|
||||
CreatedUnix: review.CreatedUnix,
|
||||
UpdatedUnix: review.UpdatedUnix,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, c := range review.Comments {
|
||||
c.ReviewID = review.ID
|
||||
}
|
||||
for _, c := range review.Comments {
|
||||
c.ReviewID = review.ID
|
||||
}
|
||||
|
||||
if len(review.Comments) > 0 {
|
||||
if _, err := sess.NoAutoTime().Insert(review.Comments); err != nil {
|
||||
if len(review.Comments) > 0 {
|
||||
if _, err := sess.NoAutoTime().Insert(review.Comments); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := UpdateIssueNumComments(ctx, review.IssueID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := UpdateIssueNumComments(ctx, review.IssueID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return committer.Commit()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// AddReviewRequest add a review request from one reviewer
|
||||
func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_model.User) (*Comment, error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer committer.Close()
|
||||
sess := db.GetEngine(ctx)
|
||||
return db.WithTx2(ctx, func(ctx context.Context) (*Comment, error) {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
review, err := GetReviewByIssueIDAndUserID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if review != nil {
|
||||
// skip it when reviewer has been request to review
|
||||
if review.Type == ReviewTypeRequest {
|
||||
return nil, committer.Commit() // still commit the transaction, or committer.Close() will rollback it, even if it's a reused transaction.
|
||||
}
|
||||
|
||||
if issue.IsClosed {
|
||||
return nil, ErrReviewRequestOnClosedPR{}
|
||||
}
|
||||
|
||||
if issue.IsPull {
|
||||
if err := issue.LoadPullRequest(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if issue.PullRequest.HasMerged {
|
||||
return nil, ErrReviewRequestOnClosedPR{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the reviewer is an official reviewer,
|
||||
// remove the official flag in the all previous reviews
|
||||
official, err := IsOfficialReviewer(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if official {
|
||||
if _, err := sess.Exec("UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_id=?", false, issue.ID, reviewer.ID); err != nil {
|
||||
review, err := GetReviewByIssueIDAndUserID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
review, err = CreateReview(ctx, CreateReviewOptions{
|
||||
Type: ReviewTypeRequest,
|
||||
Issue: issue,
|
||||
Reviewer: reviewer,
|
||||
Official: official,
|
||||
Stale: false,
|
||||
if review != nil {
|
||||
// skip it when reviewer has been request to review
|
||||
if review.Type == ReviewTypeRequest {
|
||||
return nil, nil // still commit the transaction, or committer.Close() will rollback it, even if it's a reused transaction.
|
||||
}
|
||||
|
||||
if issue.IsClosed {
|
||||
return nil, ErrReviewRequestOnClosedPR{}
|
||||
}
|
||||
|
||||
if issue.IsPull {
|
||||
if err := issue.LoadPullRequest(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if issue.PullRequest.HasMerged {
|
||||
return nil, ErrReviewRequestOnClosedPR{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the reviewer is an official reviewer,
|
||||
// remove the official flag in the all previous reviews
|
||||
official, err := IsOfficialReviewer(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if official {
|
||||
if _, err := sess.Exec("UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_id=?", false, issue.ID, reviewer.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
review, err = CreateReview(ctx, CreateReviewOptions{
|
||||
Type: ReviewTypeRequest,
|
||||
Issue: issue,
|
||||
Reviewer: reviewer,
|
||||
Official: official,
|
||||
Stale: false,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
comment, err := CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: false, // Use RemovedAssignee as !isRequest
|
||||
AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID
|
||||
ReviewID: review.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// func caller use the created comment to retrieve created review too.
|
||||
comment.Review = review
|
||||
|
||||
return comment, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
comment, err := CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: false, // Use RemovedAssignee as !isRequest
|
||||
AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID
|
||||
ReviewID: review.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// func caller use the created comment to retrieve created review too.
|
||||
comment.Review = review
|
||||
|
||||
return comment, committer.Commit()
|
||||
}
|
||||
|
||||
// RemoveReviewRequest remove a review request from one reviewer
|
||||
func RemoveReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_model.User) (*Comment, error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
review, err := GetReviewByIssueIDAndUserID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if review == nil || review.Type != ReviewTypeRequest {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if _, err = db.DeleteByBean(ctx, review); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
official, err := IsOfficialReviewer(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if official {
|
||||
if err := restoreLatestOfficialReview(ctx, issue.ID, reviewer.ID); err != nil {
|
||||
return db.WithTx2(ctx, func(ctx context.Context) (*Comment, error) {
|
||||
review, err := GetReviewByIssueIDAndUserID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
comment, err := CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: true, // Use RemovedAssignee as !isRequest
|
||||
AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID
|
||||
if review == nil || review.Type != ReviewTypeRequest {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if _, err = db.DeleteByBean(ctx, review); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
official, err := IsOfficialReviewer(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if official {
|
||||
if err := restoreLatestOfficialReview(ctx, issue.ID, reviewer.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: true, // Use RemovedAssignee as !isRequest
|
||||
AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return comment, committer.Commit()
|
||||
}
|
||||
|
||||
// Recalculate the latest official review for reviewer
|
||||
@@ -787,120 +768,112 @@ func restoreLatestOfficialReview(ctx context.Context, issueID, reviewerID int64)
|
||||
|
||||
// AddTeamReviewRequest add a review request from one team
|
||||
func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
review, err := GetTeamReviewerByIssueIDAndTeamID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This team already has been requested to review - therefore skip this.
|
||||
if review != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
official, err := IsOfficialReviewerTeam(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("isOfficialReviewerTeam(): %w", err)
|
||||
} else if !official {
|
||||
if official, err = IsOfficialReviewer(ctx, issue, doer); err != nil {
|
||||
return nil, fmt.Errorf("isOfficialReviewer(): %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if review, err = CreateReview(ctx, CreateReviewOptions{
|
||||
Type: ReviewTypeRequest,
|
||||
Issue: issue,
|
||||
ReviewerTeam: reviewer,
|
||||
Official: official,
|
||||
Stale: false,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if official {
|
||||
if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_team_id=?", false, issue.ID, reviewer.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
comment, err := CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: false, // Use RemovedAssignee as !isRequest
|
||||
AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID
|
||||
ReviewID: review.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateComment(): %w", err)
|
||||
}
|
||||
|
||||
return comment, committer.Commit()
|
||||
}
|
||||
|
||||
// RemoveTeamReviewRequest remove a review request from one team
|
||||
func RemoveTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
review, err := GetTeamReviewerByIssueIDAndTeamID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if review == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if _, err = db.DeleteByBean(ctx, review); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
official, err := IsOfficialReviewerTeam(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("isOfficialReviewerTeam(): %w", err)
|
||||
}
|
||||
|
||||
if official {
|
||||
// recalculate which is the latest official review from that team
|
||||
review, err := GetReviewByIssueIDAndUserID(ctx, issue.ID, -reviewer.ID)
|
||||
return db.WithTx2(ctx, func(ctx context.Context) (*Comment, error) {
|
||||
review, err := GetTeamReviewerByIssueIDAndTeamID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This team already has been requested to review - therefore skip this.
|
||||
if review != nil {
|
||||
if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE id=?", true, review.ID); err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
official, err := IsOfficialReviewerTeam(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("isOfficialReviewerTeam(): %w", err)
|
||||
} else if !official {
|
||||
if official, err = IsOfficialReviewer(ctx, issue, doer); err != nil {
|
||||
return nil, fmt.Errorf("isOfficialReviewer(): %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if review, err = CreateReview(ctx, CreateReviewOptions{
|
||||
Type: ReviewTypeRequest,
|
||||
Issue: issue,
|
||||
ReviewerTeam: reviewer,
|
||||
Official: official,
|
||||
Stale: false,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if official {
|
||||
if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_team_id=?", false, issue.ID, reviewer.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if doer == nil {
|
||||
return nil, committer.Commit()
|
||||
}
|
||||
comment, err := CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: false, // Use RemovedAssignee as !isRequest
|
||||
AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID
|
||||
ReviewID: review.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateComment(): %w", err)
|
||||
}
|
||||
|
||||
comment, err := CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: true, // Use RemovedAssignee as !isRequest
|
||||
AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID
|
||||
return comment, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateComment(): %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return comment, committer.Commit()
|
||||
// RemoveTeamReviewRequest remove a review request from one team
|
||||
func RemoveTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
||||
return db.WithTx2(ctx, func(ctx context.Context) (*Comment, error) {
|
||||
review, err := GetTeamReviewerByIssueIDAndTeamID(ctx, issue.ID, reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if review == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if _, err = db.DeleteByBean(ctx, review); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
official, err := IsOfficialReviewerTeam(ctx, issue, reviewer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("isOfficialReviewerTeam(): %w", err)
|
||||
}
|
||||
|
||||
if official {
|
||||
// recalculate which is the latest official review from that team
|
||||
review, err := GetReviewByIssueIDAndUserID(ctx, issue.ID, -reviewer.ID)
|
||||
if err != nil && !IsErrReviewNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if review != nil {
|
||||
if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE id=?", true, review.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if doer == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
comment, err := CreateComment(ctx, &CreateCommentOptions{
|
||||
Type: CommentTypeReviewRequest,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: true, // Use RemovedAssignee as !isRequest
|
||||
AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateComment(): %w", err)
|
||||
}
|
||||
|
||||
return comment, nil
|
||||
})
|
||||
}
|
||||
|
||||
// MarkConversation Add or remove Conversation mark for a code comment
|
||||
@@ -966,61 +939,56 @@ func CanMarkConversation(ctx context.Context, issue *Issue, doer *user_model.Use
|
||||
|
||||
// DeleteReview delete a review and it's code comments
|
||||
func DeleteReview(ctx context.Context, r *Review) error {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
if r.ID == 0 {
|
||||
return errors.New("review is not allowed to be 0")
|
||||
}
|
||||
|
||||
if r.ID == 0 {
|
||||
return errors.New("review is not allowed to be 0")
|
||||
}
|
||||
if r.Type == ReviewTypeRequest {
|
||||
return errors.New("review request can not be deleted using this method")
|
||||
}
|
||||
|
||||
if r.Type == ReviewTypeRequest {
|
||||
return errors.New("review request can not be deleted using this method")
|
||||
}
|
||||
opts := FindCommentsOptions{
|
||||
Type: CommentTypeCode,
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
opts := FindCommentsOptions{
|
||||
Type: CommentTypeCode,
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := db.Delete[Comment](ctx, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts = FindCommentsOptions{
|
||||
Type: CommentTypeReview,
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := db.Delete[Comment](ctx, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts = FindCommentsOptions{
|
||||
Type: CommentTypeDismissReview,
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := db.Delete[Comment](ctx, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := db.DeleteByID[Review](ctx, r.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Official {
|
||||
if err := restoreLatestOfficialReview(ctx, r.IssueID, r.ReviewerID); err != nil {
|
||||
if _, err := db.Delete[Comment](ctx, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return committer.Commit()
|
||||
opts = FindCommentsOptions{
|
||||
Type: CommentTypeReview,
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := db.Delete[Comment](ctx, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts = FindCommentsOptions{
|
||||
Type: CommentTypeDismissReview,
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := db.Delete[Comment](ctx, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := db.DeleteByID[Review](ctx, r.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Official {
|
||||
if err := restoreLatestOfficialReview(ctx, r.IssueID, r.ReviewerID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// GetCodeCommentsCount return count of CodeComments a Review has
|
||||
|
Reference in New Issue
Block a user