Skip to content

Commit 2b3e931

Browse files
lunnysapk
authored andcommitted
Migrate reactions when migrating repository from github (#9599)
* Migrate reactions when migrating repository from github * fix missed sleep * fix tests * update reactions when external user binding * Fix test * fix tests * change the copy head * fix test * fix migrator add/delete reaction
1 parent 4e566df commit 2b3e931

18 files changed

+329
-101
lines changed

models/external_login_user.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -177,5 +177,9 @@ func UpdateMigrationsByType(tp structs.GitServiceType, externalUserID string, us
177177
return err
178178
}
179179

180-
return UpdateReleasesMigrationsByType(tp, externalUserID, userID)
180+
if err := UpdateReleasesMigrationsByType(tp, externalUserID, userID); err != nil {
181+
return err
182+
}
183+
184+
return UpdateReactionsMigrationsByType(tp, externalUserID, userID)
181185
}

models/issue.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,11 @@ func (issue *Issue) loadReactions(e Engine) (err error) {
218218
if err != nil {
219219
return err
220220
}
221+
if err = issue.loadRepo(e); err != nil {
222+
return err
223+
}
221224
// Load reaction user data
222-
if _, err := ReactionList(reactions).loadUsers(e); err != nil {
225+
if _, err := ReactionList(reactions).loadUsers(e, issue.Repo); err != nil {
223226
return err
224227
}
225228

@@ -1836,3 +1839,17 @@ func UpdateIssuesMigrationsByType(gitServiceType structs.GitServiceType, origina
18361839
})
18371840
return err
18381841
}
1842+
1843+
// UpdateReactionsMigrationsByType updates all migrated repositories' reactions from gitServiceType to replace originalAuthorID to posterID
1844+
func UpdateReactionsMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID string, userID int64) error {
1845+
_, err := x.Table("reaction").
1846+
Join("INNER", "issue", "issue.id = reaction.issue_id").
1847+
Where("issue.repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
1848+
And("reaction.original_author_id = ?", originalAuthorID).
1849+
Update(map[string]interface{}{
1850+
"user_id": userID,
1851+
"original_author": "",
1852+
"original_author_id": 0,
1853+
})
1854+
return err
1855+
}

models/issue_comment.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ func (c *Comment) LoadDepIssueDetails() (err error) {
425425
return err
426426
}
427427

428-
func (c *Comment) loadReactions(e Engine) (err error) {
428+
func (c *Comment) loadReactions(e Engine, repo *Repository) (err error) {
429429
if c.Reactions != nil {
430430
return nil
431431
}
@@ -437,15 +437,15 @@ func (c *Comment) loadReactions(e Engine) (err error) {
437437
return err
438438
}
439439
// Load reaction user data
440-
if _, err := c.Reactions.LoadUsers(); err != nil {
440+
if _, err := c.Reactions.loadUsers(e, repo); err != nil {
441441
return err
442442
}
443443
return nil
444444
}
445445

446446
// LoadReactions loads comment reactions
447-
func (c *Comment) LoadReactions() error {
448-
return c.loadReactions(x)
447+
func (c *Comment) LoadReactions(repo *Repository) error {
448+
return c.loadReactions(x, repo)
449449
}
450450

451451
func (c *Comment) loadReview(e Engine) (err error) {

models/issue_reaction.go

+24-14
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ import (
1717

1818
// Reaction represents a reactions on issues and comments.
1919
type Reaction struct {
20-
ID int64 `xorm:"pk autoincr"`
21-
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
22-
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
23-
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
24-
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
25-
User *User `xorm:"-"`
26-
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
20+
ID int64 `xorm:"pk autoincr"`
21+
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
22+
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
23+
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
24+
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
25+
OriginalAuthorID int64 `xorm:"INDEX UNIQUE(s) NOT NULL DEFAULT(0)"`
26+
OriginalAuthor string
27+
User *User `xorm:"-"`
28+
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
2729
}
2830

2931
// FindReactionsOptions describes the conditions to Find reactions
@@ -49,7 +51,10 @@ func (opts *FindReactionsOptions) toConds() builder.Cond {
4951
cond = cond.And(builder.Eq{"reaction.comment_id": 0})
5052
}
5153
if opts.UserID > 0 {
52-
cond = cond.And(builder.Eq{"reaction.user_id": opts.UserID})
54+
cond = cond.And(builder.Eq{
55+
"reaction.user_id": opts.UserID,
56+
"reaction.original_author_id": 0,
57+
})
5358
}
5459
if opts.Reaction != "" {
5560
cond = cond.And(builder.Eq{"reaction.type": opts.Reaction})
@@ -173,7 +178,7 @@ func deleteReaction(e *xorm.Session, opts *ReactionOptions) error {
173178
if opts.Comment != nil {
174179
reaction.CommentID = opts.Comment.ID
175180
}
176-
_, err := e.Delete(reaction)
181+
_, err := e.Where("original_author_id = 0").Delete(reaction)
177182
return err
178183
}
179184

@@ -233,7 +238,7 @@ func (list ReactionList) HasUser(userID int64) bool {
233238
return false
234239
}
235240
for _, reaction := range list {
236-
if reaction.UserID == userID {
241+
if reaction.OriginalAuthor == "" && reaction.UserID == userID {
237242
return true
238243
}
239244
}
@@ -252,14 +257,17 @@ func (list ReactionList) GroupByType() map[string]ReactionList {
252257
func (list ReactionList) getUserIDs() []int64 {
253258
userIDs := make(map[int64]struct{}, len(list))
254259
for _, reaction := range list {
260+
if reaction.OriginalAuthor != "" {
261+
continue
262+
}
255263
if _, ok := userIDs[reaction.UserID]; !ok {
256264
userIDs[reaction.UserID] = struct{}{}
257265
}
258266
}
259267
return keysInt64(userIDs)
260268
}
261269

262-
func (list ReactionList) loadUsers(e Engine) ([]*User, error) {
270+
func (list ReactionList) loadUsers(e Engine, repo *Repository) ([]*User, error) {
263271
if len(list) == 0 {
264272
return nil, nil
265273
}
@@ -274,7 +282,9 @@ func (list ReactionList) loadUsers(e Engine) ([]*User, error) {
274282
}
275283

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

286296
// LoadUsers loads reactions' all users
287-
func (list ReactionList) LoadUsers() ([]*User, error) {
288-
return list.loadUsers(x)
297+
func (list ReactionList) LoadUsers(repo *Repository) ([]*User, error) {
298+
return list.loadUsers(x, repo)
289299
}
290300

291301
// GetFirstUsers returns first reacted user display names separated by comma

models/issue_reaction_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ func TestIssueCommentDeleteReaction(t *testing.T) {
132132
user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
133133

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

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

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

143-
err := comment1.LoadReactions()
144+
err := comment1.LoadReactions(repo1)
144145
assert.NoError(t, err)
145146
assert.Len(t, comment1.Reactions, 4)
146147

models/migrate.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ func insertIssue(sess *xorm.Session, issue *Issue) error {
6363
return err
6464
}
6565

66+
for _, reaction := range issue.Reactions {
67+
reaction.IssueID = issue.ID
68+
}
69+
if _, err := sess.Insert(issue.Reactions); err != nil {
70+
return err
71+
}
72+
6673
cols := make([]string, 0)
6774
if !issue.IsPull {
6875
sess.ID(issue.RepoID).Incr("num_issues")
@@ -130,9 +137,20 @@ func InsertIssueComments(comments []*Comment) error {
130137
if err := sess.Begin(); err != nil {
131138
return err
132139
}
133-
if _, err := sess.NoAutoTime().Insert(comments); err != nil {
134-
return err
140+
for _, comment := range comments {
141+
if _, err := sess.NoAutoTime().Insert(comment); err != nil {
142+
return err
143+
}
144+
145+
for _, reaction := range comment.Reactions {
146+
reaction.IssueID = comment.IssueID
147+
reaction.CommentID = comment.ID
148+
}
149+
if _, err := sess.Insert(comment.Reactions); err != nil {
150+
return err
151+
}
135152
}
153+
136154
for issueID := range issueIDs {
137155
if _, err := sess.Exec("UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ?) WHERE id = ?", issueID, issueID); err != nil {
138156
return err

models/migrations/migrations.go

+2
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ var migrations = []Migration{
300300
NewMigration("add is_restricted column for users table", addIsRestricted),
301301
// v122 -> v123
302302
NewMigration("Add Require Signed Commits to ProtectedBranch", addRequireSignedCommits),
303+
// v123 -> v124
304+
NewMigration("Add original informations for reactions", addReactionOriginals),
303305
}
304306

305307
// Migrate database to current version

models/migrations/v123.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2020 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"xorm.io/xorm"
9+
)
10+
11+
func addReactionOriginals(x *xorm.Engine) error {
12+
type Reaction struct {
13+
OriginalAuthorID int64 `xorm:"INDEX NOT NULL DEFAULT(0)"`
14+
OriginalAuthor string
15+
}
16+
17+
return x.Sync2(new(Reaction))
18+
}

models/user.go

+9
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,15 @@ func NewGhostUser() *User {
793793
}
794794
}
795795

796+
// NewReplaceUser creates and returns a fake user for external user
797+
func NewReplaceUser(name string) *User {
798+
return &User{
799+
ID: -1,
800+
Name: name,
801+
LowerName: strings.ToLower(name),
802+
}
803+
}
804+
796805
// IsGhost check if user is fake user for a deleted account
797806
func (u *User) IsGhost() bool {
798807
if u == nil {

modules/migrations/base/comment.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ type Comment struct {
1616
Created time.Time
1717
Updated time.Time
1818
Content string
19-
Reactions *Reactions
19+
Reactions []*Reaction
2020
}

modules/migrations/base/issue.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ type Issue struct {
2222
Updated time.Time
2323
Closed *time.Time
2424
Labels []*Label
25-
Reactions *Reactions
25+
Reactions []*Reaction
2626
}

modules/migrations/base/pullrequest.go

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type PullRequest struct {
3333
Assignee string
3434
Assignees []string
3535
IsLocked bool
36+
Reactions []*Reaction
3637
}
3738

3839
// IsForkPullRequest returns true if the pull request from a forked repository but not the same repository

modules/migrations/base/reaction.go

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
// Copyright 2019 The Gitea Authors. All rights reserved.
2-
// Copyright 2018 Jonas Franz. All rights reserved.
1+
// Copyright 2020 The Gitea Authors. All rights reserved.
32
// Use of this source code is governed by a MIT-style
43
// license that can be found in the LICENSE file.
54

65
package base
76

8-
// Reactions represents a summary of reactions.
9-
type Reactions struct {
10-
TotalCount int
11-
PlusOne int
12-
MinusOne int
13-
Laugh int
14-
Confused int
15-
Heart int
16-
Hooray int
7+
// Reaction represents a reaction to an issue/pr/comment.
8+
type Reaction struct {
9+
UserID int64
10+
UserName string
11+
Content string
1712
}

0 commit comments

Comments
 (0)