Repository: go-gitea/gitea
File: models/pull/review_state.go (Go)

Code before:
	review, exists, err := GetReviewState(ctx, userID, pullID, commitSHA)
	if err != nil {
		return nil, err
	}

	if exists {
		review.UpdatedFiles = mergeFiles(review.UpdatedFiles, updatedFiles)
	} else if previousReview, err := getNewestReviewStateApartFrom(ctx, userID, pullID, commitSHA); err != nil {
		return nil, err

		// Overwrite the viewed files of the previous review if present
	} else if previousReview != nil {
		review.UpdatedFiles = mergeFiles(previousReview.UpdatedFiles, updatedFiles)
	} else {
		review.UpdatedFiles = updatedFiles
	}

	// Insert or Update review
	engine := db.GetEngine(ctx)
	if !exists {
		log.Trace("Inserting new review for user %d, repo %d, commit %s with the updated files %v.", userID, pullID, commitSHA, review.UpdatedFiles)
		_, err := engine.Insert(review)
		return nil, err
	}
	log.Trace("Updating already existing review with ID %d (user %d, repo %d, commit %s) with the updated files %v.", review.ID, userID, pullID, commitSHA, review.UpdatedFiles)
	_, err = engine.ID(review.ID).Update(&ReviewState{UpdatedFiles: review.UpdatedFiles})
	return review, err
}

// mergeFiles merges the given maps of files with their viewing state into one map.
// Values from oldFiles will be overridden with values from newFiles
func mergeFiles(oldFiles, newFiles map[string]ViewedState) map[string]ViewedState {
	if oldFiles == nil {
		return newFiles
	} else if newFiles == nil {
		return oldFiles
	}

	maps.Copy(oldFiles, newFiles)
	return oldFiles
}

// GetNewestReviewState gets the newest review of the current user in the current PR.
// The returned PR Review will be nil if the user has not yet reviewed this PR.
func GetNewestReviewState(ctx context.Context, userID, pullID int64) (*ReviewState, error) {
	var review ReviewState
	has, err := db.GetEngine(ctx).Where("user_id = ?", userID).And("pull_id = ?", pullID).OrderBy("updated_unix DESC").Get(&review)
	if err != nil || !has {
		return nil, err
	}
	return &review, err

Review comment (suggestion):
Unrelated to this issue but it's better to have a `.Cols("updated_files")` here to limit the possible updated column.

Code after:
	review, exists, err := GetReviewState(ctx, userID, pullID, commitSHA)
	if err != nil {
		return nil, err
	}

	if exists {
		review.UpdatedFiles = mergeFiles(review.UpdatedFiles, updatedFiles)
	} else if previousReview, err := getNewestReviewStateApartFrom(ctx, userID, pullID, commitSHA); err != nil {
		return nil, err

		// Overwrite the viewed files of the previous review if present
	} else if previousReview != nil {
		review.UpdatedFiles = mergeFiles(previousReview.UpdatedFiles, updatedFiles)
	} else {
		review.UpdatedFiles = updatedFiles
	}

	// Insert or Update review
	engine := db.GetEngine(ctx)
	if !exists {
		log.Trace("Inserting new review for user %d, repo %d, commit %s with the updated files %v.", userID, pullID, commitSHA, review.UpdatedFiles)
		_, err := engine.Insert(review)
		return nil, err
	}
	log.Trace("Updating already existing review with ID %d (user %d, repo %d, commit %s) with the updated files %v.", review.ID, userID, pullID, commitSHA, review.UpdatedFiles)
	_, err = engine.ID(review.ID).Cols("updated_files").Update(review)
	return review, err
}

// mergeFiles merges the given maps of files with their viewing state into one map.
// Values from oldFiles will be overridden with values from newFiles
func mergeFiles(oldFiles, newFiles map[string]ViewedState) map[string]ViewedState {
	if oldFiles == nil {
		return newFiles
	} else if newFiles == nil {
		return oldFiles
	}

	maps.Copy(oldFiles, newFiles)
	return oldFiles
}

// GetNewestReviewState gets the newest review of the current user in the current PR.
// The returned PR Review will be nil if the user has not yet reviewed this PR.
func GetNewestReviewState(ctx context.Context, userID, pullID int64) (*ReviewState, error) {
	var review ReviewState
	has, err := db.GetEngine(ctx).Where("user_id = ?", userID).And("pull_id = ?", pullID).OrderBy("updated_unix DESC").Get(&review)
	if err != nil || !has {
		return nil, err
	}
	return &review, err