diff --git a/models/issues/review.go b/models/issues/review.go index 5835900801..ba12876dc5 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -626,17 +626,7 @@ func InsertReviews(reviews []*Review) error { 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 { + if _, err := sess.NoAutoTime().Insert(generateCommentFromReview(review)); err != nil { return err } @@ -654,6 +644,112 @@ func InsertReviews(reviews []*Review) error { return committer.Commit() } +// UpsertReviews inserts new reviews and updates existing ones. +// This function is used for syncing from the pull mirror. +func UpsertReviews(reviews []*Review) error { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + sess := db.GetEngine(ctx) + + for _, review := range reviews { + exists, err := sess.Where("issue_id = ? AND created_unix", review.IssueID, review.CreatedUnix).Exist(&Review{}) + if err != nil { + return err + } + + if !exists { + if _, err := sess.NoAutoTime().Insert(review); err != nil { + return err + } + + if _, err := sess.NoAutoTime().Insert(generateCommentFromReview(review)); err != nil { + return err + } + + for _, c := range review.Comments { + c.ReviewID = review.ID + } + + if len(review.Comments) > 0 { + if _, err := sess.NoAutoTime().Insert(review.Comments); err != nil { + return err + } + } + } else { + if _, err = sess.NoAutoTime().Where("issue_id = ? AND created_unix", review.IssueID, review.CreatedUnix).Update(review); err != nil { + return err + } + + // Get id of the review + if err = sess.NoAutoTime().Where("issue_id = ? AND created_unix", review.IssueID, review.CreatedUnix).Find(review); err != nil { + return err + } + + comment := generateCommentFromReview(review) + exists, err := existsCommentByReviewIDAndCreatedUnix(sess, comment) + if err != nil { + return err + } + + if !exists { + if _, err := sess.NoAutoTime().Insert(comment); err != nil { + return err + } + } else { + if _, err := sess.NoAutoTime().Where("review_id = ? AND created_unix = ?", review.ID, comment.CreatedUnix).Update(comment); err != nil { + return err + } + } + + for _, c := range review.Comments { + c.ReviewID = review.ID + } + + if len(review.Comments) > 0 { + for _, comment := range review.Comments { + exists, err := existsCommentByReviewIDAndCreatedUnix(sess, comment) + if err != nil { + return err + } + + if !exists { + if _, err := sess.NoAutoTime().Insert(comment); err != nil { + return err + } + } else { + if _, err := sess.NoAutoTime().Where("review_id = ? AND created_unix = ?", review.ID, comment.CreatedUnix).Update(comment); err != nil { + return err + } + } + } + } + } + } + + return committer.Commit() +} + +func existsCommentByReviewIDAndCreatedUnix(sess db.Engine, comment *Comment) (bool, error) { + return sess.Where("review_id = ? AND created_unix = ?", comment.ReviewID, comment.CreatedUnix).Exist(&Comment{}) +} + +func generateCommentFromReview(review *Review) *Comment { + return &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, + } +} + // AddReviewRequest add a review request from one reviewer func AddReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment, error) { ctx, committer, err := db.TxContext() diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index f23a8a1439..559240a80a 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -747,14 +747,13 @@ func convertReviewState(state string) issues_model.ReviewType { } } -// CreateReviews create pull request reviews of currently migrated issues -func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { +func (g *GiteaLocalUploader) prepareReviews(reviews ...*base.Review) ([]*issues_model.Review, error) { cms := make([]*issues_model.Review, 0, len(reviews)) for _, review := range reviews { var issue *issues_model.Issue issue, ok := g.issues[review.IssueIndex] if !ok { - return fmt.Errorf("review references non existent IssueIndex %d", review.IssueIndex) + return nil, fmt.Errorf("review references non existent IssueIndex %d", review.IssueIndex) } if review.CreatedAt.IsZero() { review.CreatedAt = time.Unix(int64(issue.CreatedUnix), 0) @@ -770,7 +769,7 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { } if err := g.remapUser(review, &cm); err != nil { - return err + return nil, err } // get pr @@ -779,7 +778,7 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { var err error pr, err = issues_model.GetPullRequestByIssueIDWithNoAttributes(issue.ID) if err != nil { - return err + return nil, err } g.prCache[issue.ID] = pr } @@ -833,7 +832,7 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { } if err := g.remapUser(review, &c); err != nil { - return err + return nil, err } cm.Comments = append(cm.Comments, &c) @@ -842,6 +841,16 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { cms = append(cms, &cm) } + return cms, nil +} + +// CreateReviews create pull request reviews of currently migrated issues +func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { + cms, err := g.prepareReviews(reviews...) + if err != nil { + return err + } + return issues_model.InsertReviews(cms) } @@ -932,7 +941,12 @@ func (g *GiteaLocalUploader) PatchPullRequests(prs ...*base.PullRequest) error { } func (g *GiteaLocalUploader) PatchReviews(reviews ...*base.Review) error { - return nil + cms, err := g.prepareReviews(reviews...) + if err != nil { + return err + } + + return issues_model.UpsertReviews(cms) } // Rollback when migrating failed, this will rollback all the changes.