Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate reactions when migrating repository from github #9599

Merged
merged 9 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion models/external_login_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,9 @@ func UpdateMigrationsByType(tp structs.GitServiceType, externalUserID string, us
return err
}

return UpdateReleasesMigrationsByType(tp, externalUserID, userID)
if err := UpdateReleasesMigrationsByType(tp, externalUserID, userID); err != nil {
return err
}

return UpdateReactionsMigrationsByType(tp, externalUserID, userID)
}
19 changes: 18 additions & 1 deletion models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,11 @@ func (issue *Issue) loadReactions(e Engine) (err error) {
if err != nil {
return err
}
if err = issue.loadRepo(e); err != nil {
return err
}
// Load reaction user data
if _, err := ReactionList(reactions).loadUsers(e); err != nil {
if _, err := ReactionList(reactions).loadUsers(e, issue.Repo); err != nil {
return err
}

Expand Down Expand Up @@ -1836,3 +1839,17 @@ func UpdateIssuesMigrationsByType(gitServiceType structs.GitServiceType, origina
})
return err
}

// UpdateReactionsMigrationsByType updates all migrated repositories' reactions from gitServiceType to replace originalAuthorID to posterID
func UpdateReactionsMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID string, userID int64) error {
_, err := x.Table("reaction").
Join("INNER", "issue", "issue.id = reaction.issue_id").
Where("issue.repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
And("reaction.original_author_id = ?", originalAuthorID).
Update(map[string]interface{}{
"user_id": userID,
"original_author": "",
"original_author_id": 0,
})
return err
}
8 changes: 4 additions & 4 deletions models/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ func (c *Comment) LoadDepIssueDetails() (err error) {
return err
}

func (c *Comment) loadReactions(e Engine) (err error) {
func (c *Comment) loadReactions(e Engine, repo *Repository) (err error) {
if c.Reactions != nil {
return nil
}
Expand All @@ -437,15 +437,15 @@ func (c *Comment) loadReactions(e Engine) (err error) {
return err
}
// Load reaction user data
if _, err := c.Reactions.LoadUsers(); err != nil {
if _, err := c.Reactions.loadUsers(e, repo); err != nil {
return err
}
return nil
}

// LoadReactions loads comment reactions
func (c *Comment) LoadReactions() error {
return c.loadReactions(x)
func (c *Comment) LoadReactions(repo *Repository) error {
return c.loadReactions(x, repo)
}

func (c *Comment) loadReview(e Engine) (err error) {
Expand Down
38 changes: 24 additions & 14 deletions models/issue_reaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ import (

// Reaction represents a reactions on issues and comments.
type Reaction struct {
ID int64 `xorm:"pk autoincr"`
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
User *User `xorm:"-"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
ID int64 `xorm:"pk autoincr"`
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
OriginalAuthorID int64 `xorm:"INDEX UNIQUE(s) NOT NULL DEFAULT(0)"`
OriginalAuthor string
User *User `xorm:"-"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
}

// FindReactionsOptions describes the conditions to Find reactions
Expand All @@ -49,7 +51,10 @@ func (opts *FindReactionsOptions) toConds() builder.Cond {
cond = cond.And(builder.Eq{"reaction.comment_id": 0})
}
if opts.UserID > 0 {
cond = cond.And(builder.Eq{"reaction.user_id": opts.UserID})
cond = cond.And(builder.Eq{
"reaction.user_id": opts.UserID,
"reaction.original_author_id": 0,
})
}
if opts.Reaction != "" {
cond = cond.And(builder.Eq{"reaction.type": opts.Reaction})
Expand Down Expand Up @@ -173,7 +178,7 @@ func deleteReaction(e *xorm.Session, opts *ReactionOptions) error {
if opts.Comment != nil {
reaction.CommentID = opts.Comment.ID
}
_, err := e.Delete(reaction)
_, err := e.Where("original_author_id = 0").Delete(reaction)
return err
}

Expand Down Expand Up @@ -233,7 +238,7 @@ func (list ReactionList) HasUser(userID int64) bool {
return false
}
for _, reaction := range list {
if reaction.UserID == userID {
if reaction.OriginalAuthor == "" && reaction.UserID == userID {
lunny marked this conversation as resolved.
Show resolved Hide resolved
return true
}
}
Expand All @@ -252,14 +257,17 @@ func (list ReactionList) GroupByType() map[string]ReactionList {
func (list ReactionList) getUserIDs() []int64 {
userIDs := make(map[int64]struct{}, len(list))
for _, reaction := range list {
if reaction.OriginalAuthor != "" {
continue
}
if _, ok := userIDs[reaction.UserID]; !ok {
userIDs[reaction.UserID] = struct{}{}
}
}
return keysInt64(userIDs)
}

func (list ReactionList) loadUsers(e Engine) ([]*User, error) {
func (list ReactionList) loadUsers(e Engine, repo *Repository) ([]*User, error) {
if len(list) == 0 {
return nil, nil
}
Expand All @@ -274,7 +282,9 @@ func (list ReactionList) loadUsers(e Engine) ([]*User, error) {
}

for _, reaction := range list {
if user, ok := userMaps[reaction.UserID]; ok {
if reaction.OriginalAuthor != "" {
reaction.User = NewReplaceUser(fmt.Sprintf("%s(%s)", reaction.OriginalAuthor, repo.OriginalServiceType.Name()))
} else if user, ok := userMaps[reaction.UserID]; ok {
reaction.User = user
} else {
reaction.User = NewGhostUser()
Expand All @@ -284,8 +294,8 @@ func (list ReactionList) loadUsers(e Engine) ([]*User, error) {
}

// LoadUsers loads reactions' all users
func (list ReactionList) LoadUsers() ([]*User, error) {
return list.loadUsers(x)
func (list ReactionList) LoadUsers(repo *Repository) ([]*User, error) {
return list.loadUsers(x, repo)
}

// GetFirstUsers returns first reacted user display names separated by comma
Expand Down
3 changes: 2 additions & 1 deletion models/issue_reaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func TestIssueCommentDeleteReaction(t *testing.T) {
user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)

issue1 := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
repo1 := AssertExistsAndLoadBean(t, &Repository{ID: issue1.RepoID}).(*Repository)

comment1 := AssertExistsAndLoadBean(t, &Comment{ID: 1}).(*Comment)

Expand All @@ -140,7 +141,7 @@ func TestIssueCommentDeleteReaction(t *testing.T) {
addReaction(t, user3, issue1, comment1, "heart")
addReaction(t, user4, issue1, comment1, "+1")

err := comment1.LoadReactions()
err := comment1.LoadReactions(repo1)
assert.NoError(t, err)
assert.Len(t, comment1.Reactions, 4)

Expand Down
22 changes: 20 additions & 2 deletions models/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ func insertIssue(sess *xorm.Session, issue *Issue) error {
return err
}

for _, reaction := range issue.Reactions {
reaction.IssueID = issue.ID
}
if _, err := sess.Insert(issue.Reactions); err != nil {
return err
}

cols := make([]string, 0)
if !issue.IsPull {
sess.ID(issue.RepoID).Incr("num_issues")
Expand Down Expand Up @@ -130,9 +137,20 @@ func InsertIssueComments(comments []*Comment) error {
if err := sess.Begin(); err != nil {
return err
}
if _, err := sess.NoAutoTime().Insert(comments); err != nil {
return err
for _, comment := range comments {
if _, err := sess.NoAutoTime().Insert(comment); err != nil {
return err
}

for _, reaction := range comment.Reactions {
reaction.IssueID = comment.IssueID
reaction.CommentID = comment.ID
}
if _, err := sess.Insert(comment.Reactions); err != nil {
return err
}
}

for issueID := range issueIDs {
if _, err := sess.Exec("UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ?) WHERE id = ?", issueID, issueID); err != nil {
return err
Expand Down
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ var migrations = []Migration{
NewMigration("add is_restricted column for users table", addIsRestricted),
// v122 -> v123
NewMigration("Add Require Signed Commits to ProtectedBranch", addRequireSignedCommits),
// v123 -> v124
NewMigration("Add original informations for reactions", addReactionOriginals),
}

// Migrate database to current version
Expand Down
18 changes: 18 additions & 0 deletions models/migrations/v123.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2020 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 migrations

import (
"xorm.io/xorm"
)

func addReactionOriginals(x *xorm.Engine) error {
type Reaction struct {
OriginalAuthorID int64 `xorm:"INDEX NOT NULL DEFAULT(0)"`
OriginalAuthor string
}

return x.Sync2(new(Reaction))
}
9 changes: 9 additions & 0 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,15 @@ func NewGhostUser() *User {
}
}

// NewReplaceUser creates and returns a fake user for external user
func NewReplaceUser(name string) *User {
return &User{
ID: -1,
Name: name,
LowerName: strings.ToLower(name),
}
}

// IsGhost check if user is fake user for a deleted account
func (u *User) IsGhost() bool {
if u == nil {
Expand Down
2 changes: 1 addition & 1 deletion modules/migrations/base/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ type Comment struct {
Created time.Time
Updated time.Time
Content string
Reactions *Reactions
Reactions []*Reaction
}
2 changes: 1 addition & 1 deletion modules/migrations/base/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ type Issue struct {
Updated time.Time
Closed *time.Time
Labels []*Label
Reactions *Reactions
Reactions []*Reaction
}
1 change: 1 addition & 0 deletions modules/migrations/base/pullrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type PullRequest struct {
Assignee string
Assignees []string
IsLocked bool
Reactions []*Reaction
}

// IsForkPullRequest returns true if the pull request from a forked repository but not the same repository
Expand Down
17 changes: 6 additions & 11 deletions modules/migrations/base/reaction.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Copyright 2018 Jonas Franz. All rights reserved.
// Copyright 2020 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 base

// Reactions represents a summary of reactions.
type Reactions struct {
TotalCount int
PlusOne int
MinusOne int
Laugh int
Confused int
Heart int
Hooray int
// Reaction represents a reaction to an issue/pr/comment.
type Reaction struct {
UserID int64
UserName string
Content string
}
Loading