From 6ac563a8597b03d179382dfca9a21358910279dc Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 4 Jan 2020 20:29:41 +0800 Subject: [PATCH 1/9] Migrate reactions when migrating repository from github --- models/issue_reaction.go | 16 +++-- models/migrate.go | 21 +++++- models/migrations/migrations.go | 2 + models/migrations/v123.go | 18 ++++++ modules/migrations/base/comment.go | 2 +- modules/migrations/base/issue.go | 2 +- modules/migrations/base/pullrequest.go | 1 + modules/migrations/base/reaction.go | 14 ++-- modules/migrations/gitea.go | 90 ++++++++++++++++++++++++-- modules/migrations/github.go | 90 +++++++++++++++++++------- 10 files changed, 208 insertions(+), 48 deletions(-) create mode 100644 models/migrations/v123.go diff --git a/models/issue_reaction.go b/models/issue_reaction.go index d421ab44e92d4..74fa6db37dd4d 100644 --- a/models/issue_reaction.go +++ b/models/issue_reaction.go @@ -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"` + OriginalAuthor string + User *User `xorm:"-"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` } // FindReactionsOptions describes the conditions to Find reactions diff --git a/models/migrate.go b/models/migrate.go index 53838fd65e742..61ea5b3cb4eaa 100644 --- a/models/migrate.go +++ b/models/migrate.go @@ -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") @@ -130,9 +137,19 @@ 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.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 diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index edea36cf79340..e86ca8e4fe100 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -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 diff --git a/models/migrations/v123.go b/models/migrations/v123.go new file mode 100644 index 0000000000000..e1b772381e11d --- /dev/null +++ b/models/migrations/v123.go @@ -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)) +} diff --git a/modules/migrations/base/comment.go b/modules/migrations/base/comment.go index 94cbabaae62f3..4a653e474b0f5 100644 --- a/modules/migrations/base/comment.go +++ b/modules/migrations/base/comment.go @@ -16,5 +16,5 @@ type Comment struct { Created time.Time Updated time.Time Content string - Reactions *Reactions + Reactions []*Reaction } diff --git a/modules/migrations/base/issue.go b/modules/migrations/base/issue.go index b87a7fec622ec..4e2bf25f1772c 100644 --- a/modules/migrations/base/issue.go +++ b/modules/migrations/base/issue.go @@ -22,5 +22,5 @@ type Issue struct { Updated time.Time Closed *time.Time Labels []*Label - Reactions *Reactions + Reactions []*Reaction } diff --git a/modules/migrations/base/pullrequest.go b/modules/migrations/base/pullrequest.go index b1602b8218622..3a1e0f25bd3ea 100644 --- a/modules/migrations/base/pullrequest.go +++ b/modules/migrations/base/pullrequest.go @@ -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 diff --git a/modules/migrations/base/reaction.go b/modules/migrations/base/reaction.go index fd7a9543d34b6..ee751b3941613 100644 --- a/modules/migrations/base/reaction.go +++ b/modules/migrations/base/reaction.go @@ -5,13 +5,9 @@ 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 } diff --git a/modules/migrations/gitea.go b/modules/migrations/gitea.go index 0cffd60e84e6c..82664d0d1a30f 100644 --- a/modules/migrations/gitea.go +++ b/modules/migrations/gitea.go @@ -361,7 +361,32 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error { if issue.Closed != nil { is.ClosedUnix = timeutil.TimeStamp(issue.Closed.Unix()) } - // TODO: add reactions + // add reactions + for _, reaction := range issue.Reactions { + userid, ok := g.userMap[reaction.UserID] + if !ok && tp != "" { + var err error + userid, err = models.GetUserIDByExternalUserID(tp, fmt.Sprintf("%v", reaction.UserID)) + if err != nil { + log.Error("GetUserIDByExternalUserID: %v", err) + } + if userid > 0 { + g.userMap[reaction.UserID] = userid + } + } + var res = models.Reaction{ + Type: reaction.Content, + CreatedUnix: timeutil.TimeStampNow(), + } + if userid > 0 { + res.UserID = userid + } else { + res.UserID = g.doer.ID + res.OriginalAuthorID = reaction.UserID + res.OriginalAuthor = reaction.UserName + } + is.Reactions = append(is.Reactions, &res) + } iss = append(iss, &is) } @@ -420,9 +445,34 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error { cm.OriginalAuthorID = comment.PosterID } - cms = append(cms, &cm) + // add reactions + for _, reaction := range comment.Reactions { + userid, ok := g.userMap[reaction.UserID] + if !ok && tp != "" { + var err error + userid, err = models.GetUserIDByExternalUserID(tp, fmt.Sprintf("%v", reaction.UserID)) + if err != nil { + log.Error("GetUserIDByExternalUserID: %v", err) + } + if userid > 0 { + g.userMap[reaction.UserID] = userid + } + } + var res = models.Reaction{ + Type: reaction.Content, + CreatedUnix: timeutil.TimeStampNow(), + } + if userid > 0 { + res.UserID = userid + } else { + res.UserID = g.doer.ID + res.OriginalAuthorID = reaction.UserID + res.OriginalAuthor = reaction.UserName + } + cm.Reactions = append(cm.Reactions, &res) + } - // TODO: Reactions + cms = append(cms, &cm) } return models.InsertIssueComments(cms) @@ -581,10 +631,12 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR UpdatedUnix: timeutil.TimeStamp(pr.Updated.Unix()), } + tp := g.gitServiceType.Name() + userid, ok := g.userMap[pr.PosterID] - if !ok { + if !ok && tp != "" { var err error - userid, err = models.GetUserIDByExternalUserID("github", fmt.Sprintf("%v", pr.PosterID)) + userid, err = models.GetUserIDByExternalUserID(tp, fmt.Sprintf("%v", pr.PosterID)) if err != nil { log.Error("GetUserIDByExternalUserID: %v", err) } @@ -601,6 +653,33 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR issue.OriginalAuthorID = pr.PosterID } + // add reactions + for _, reaction := range pr.Reactions { + userid, ok := g.userMap[reaction.UserID] + if !ok && tp != "" { + var err error + userid, err = models.GetUserIDByExternalUserID(tp, fmt.Sprintf("%v", reaction.UserID)) + if err != nil { + log.Error("GetUserIDByExternalUserID: %v", err) + } + if userid > 0 { + g.userMap[reaction.UserID] = userid + } + } + var res = models.Reaction{ + Type: reaction.Content, + CreatedUnix: timeutil.TimeStampNow(), + } + if userid > 0 { + res.UserID = userid + } else { + res.UserID = g.doer.ID + res.OriginalAuthorID = reaction.UserID + res.OriginalAuthor = reaction.UserName + } + issue.Reactions = append(issue.Reactions, &res) + } + var pullRequest = models.PullRequest{ HeadRepoID: g.repo.ID, HeadBranch: head, @@ -622,7 +701,6 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR pullRequest.MergerID = g.doer.ID } - // TODO: reactions // TODO: assignees return &pullRequest, nil diff --git a/modules/migrations/github.go b/modules/migrations/github.go index 9183c9318fb7e..c986ac81d419e 100644 --- a/modules/migrations/github.go +++ b/modules/migrations/github.go @@ -319,18 +319,6 @@ func (g *GithubDownloaderV3) GetReleases() ([]*base.Release, error) { return releases, nil } -func convertGithubReactions(reactions *github.Reactions) *base.Reactions { - return &base.Reactions{ - TotalCount: *reactions.TotalCount, - PlusOne: *reactions.PlusOne, - MinusOne: *reactions.MinusOne, - Laugh: *reactions.Laugh, - Confused: *reactions.Confused, - Heart: *reactions.Heart, - Hooray: *reactions.Hooray, - } -} - // GetIssues returns issues according start and limit func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool, error) { opt := &github.IssueListByRepoOptions{ @@ -366,15 +354,34 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool, for _, l := range issue.Labels { labels = append(labels, convertGithubLabel(&l)) } - var reactions *base.Reactions - if issue.Reactions != nil { - reactions = convertGithubReactions(issue.Reactions) - } var email string if issue.User.Email != nil { email = *issue.User.Email } + + // get reactions + var reactions []*base.Reaction + for i := 0; ; i++ { + res, _, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListOptions{ + Page: i, + PerPage: perPage, + }) + if err != nil { + return nil, false, err + } + if len(res) == 0 { + break + } + for _, reaction := range res { + reactions = append(reactions, &base.Reaction{ + UserID: reaction.User.GetID(), + UserName: reaction.User.GetLogin(), + Content: reaction.GetContent(), + }) + } + } + allIssues = append(allIssues, &base.Issue{ Title: *issue.Title, Number: int64(*issue.Number), @@ -418,9 +425,27 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er if comment.User.Email != nil { email = *comment.User.Email } - var reactions *base.Reactions - if comment.Reactions != nil { - reactions = convertGithubReactions(comment.Reactions) + + // get reactions + var reactions []*base.Reaction + for i := 0; ; i++ { + res, _, err := g.client.Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{ + Page: i, + PerPage: 100, + }) + if err != nil { + return nil, err + } + if len(res) == 0 { + break + } + for _, reaction := range res { + reactions = append(reactions, &base.Reaction{ + UserID: reaction.User.GetID(), + UserName: reaction.User.GetLogin(), + Content: reaction.GetContent(), + }) + } } allComments = append(allComments, &base.Comment{ IssueIndex: issueNumber, @@ -473,8 +498,6 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq labels = append(labels, convertGithubLabel(l)) } - // FIXME: This API missing reactions, we may need another extra request to get reactions - var email string if pr.User.Email != nil { email = *pr.User.Email @@ -515,6 +538,28 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq headUserName = *pr.Head.User.Login } + // get reactions + var reactions []*base.Reaction + for i := 0; ; i++ { + res, _, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListOptions{ + Page: i, + PerPage: perPage, + }) + if err != nil { + return nil, err + } + if len(res) == 0 { + break + } + for _, reaction := range res { + reactions = append(reactions, &base.Reaction{ + UserID: reaction.User.GetID(), + UserName: reaction.User.GetLogin(), + Content: reaction.GetContent(), + }) + } + } + allPRs = append(allPRs, &base.PullRequest{ Title: *pr.Title, Number: int64(*pr.Number), @@ -545,7 +590,8 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq RepoName: *pr.Base.Repo.Name, OwnerName: *pr.Base.User.Login, }, - PatchURL: *pr.PatchURL, + PatchURL: *pr.PatchURL, + Reactions: reactions, }) } From b4ebba72d645bad2d290fb9a8a72aa7c9eb13c7b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 4 Jan 2020 21:36:11 +0800 Subject: [PATCH 2/9] fix missed sleep --- modules/migrations/github.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/migrations/github.go b/modules/migrations/github.go index c986ac81d419e..914e4f6168151 100644 --- a/modules/migrations/github.go +++ b/modules/migrations/github.go @@ -363,13 +363,15 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool, // get reactions var reactions []*base.Reaction for i := 0; ; i++ { - res, _, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListOptions{ + g.sleep() + res, resp, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListOptions{ Page: i, PerPage: perPage, }) if err != nil { return nil, false, err } + g.rate = &resp.Rate if len(res) == 0 { break } @@ -429,13 +431,15 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er // get reactions var reactions []*base.Reaction for i := 0; ; i++ { - res, _, err := g.client.Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{ + g.sleep() + res, resp, err := g.client.Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{ Page: i, PerPage: 100, }) if err != nil { return nil, err } + g.rate = &resp.Rate if len(res) == 0 { break } @@ -541,13 +545,15 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq // get reactions var reactions []*base.Reaction for i := 0; ; i++ { - res, _, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListOptions{ + g.sleep() + res, resp, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListOptions{ Page: i, PerPage: perPage, }) if err != nil { return nil, err } + g.rate = &resp.Rate if len(res) == 0 { break } From 962d0c3eb983efa22719484b41666c67876e9d31 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 10 Jan 2020 17:18:42 +0800 Subject: [PATCH 3/9] fix tests --- modules/migrations/github.go | 6 +-- modules/migrations/github_test.go | 89 +++++++++++++++++++------------ 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/modules/migrations/github.go b/modules/migrations/github.go index 914e4f6168151..17e49d90d1905 100644 --- a/modules/migrations/github.go +++ b/modules/migrations/github.go @@ -362,7 +362,7 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool, // get reactions var reactions []*base.Reaction - for i := 0; ; i++ { + for i := 1; ; i++ { g.sleep() res, resp, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListOptions{ Page: i, @@ -430,7 +430,7 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er // get reactions var reactions []*base.Reaction - for i := 0; ; i++ { + for i := 1; ; i++ { g.sleep() res, resp, err := g.client.Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{ Page: i, @@ -544,7 +544,7 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq // get reactions var reactions []*base.Reaction - for i := 0; ; i++ { + for i := 1; ; i++ { g.sleep() res, resp, err := g.client.Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListOptions{ Page: i, diff --git a/modules/migrations/github_test.go b/modules/migrations/github_test.go index bf71ab4756ab0..db120580e8ba6 100644 --- a/modules/migrations/github_test.go +++ b/modules/migrations/github_test.go @@ -170,14 +170,12 @@ func TestGitHubDownloadRepo(t *testing.T) { Description: "Good for newcomers", }, }, - Reactions: &base.Reactions{ - TotalCount: 1, - PlusOne: 1, - MinusOne: 0, - Laugh: 0, - Confused: 0, - Heart: 0, - Hooray: 0, + Reactions: []*base.Reaction{ + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "+1", + }, }, Closed: &closed1, }, @@ -198,14 +196,37 @@ func TestGitHubDownloadRepo(t *testing.T) { Description: "This issue or pull request already exists", }, }, - Reactions: &base.Reactions{ - TotalCount: 6, - PlusOne: 1, - MinusOne: 1, - Laugh: 1, - Confused: 1, - Heart: 1, - Hooray: 1, + Reactions: []*base.Reaction{ + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "heart", + }, + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "laugh", + }, + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "confused", + }, + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "hooray", + }, + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "+1", + }, + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "+1", + }, }, Closed: &closed2, }, @@ -223,14 +244,12 @@ func TestGitHubDownloadRepo(t *testing.T) { Created: time.Date(2019, 11, 12, 21, 0, 13, 0, time.UTC), Updated: time.Date(2019, 11, 12, 21, 0, 13, 0, time.UTC), Content: "This is a comment", - Reactions: &base.Reactions{ - TotalCount: 1, - PlusOne: 1, - MinusOne: 0, - Laugh: 0, - Confused: 0, - Heart: 0, - Hooray: 0, + Reactions: []*base.Reaction{ + { + UserID: 1669571, + UserName: "mrsdizzie", + Content: "+1", + }, }, }, { @@ -240,15 +259,7 @@ func TestGitHubDownloadRepo(t *testing.T) { Created: time.Date(2019, 11, 12, 22, 7, 14, 0, time.UTC), Updated: time.Date(2019, 11, 12, 22, 7, 14, 0, time.UTC), Content: "A second comment", - Reactions: &base.Reactions{ - TotalCount: 0, - PlusOne: 0, - MinusOne: 0, - Laugh: 0, - Confused: 0, - Heart: 0, - Hooray: 0, - }, + Reactions: nil, }, }, comments[:2]) @@ -331,6 +342,18 @@ func TestGitHubDownloadRepo(t *testing.T) { }, Merged: false, MergeCommitSHA: "565d1208f5fffdc1c5ae1a2436491eb9a5e4ebae", + Reactions: []*base.Reaction{ + { + UserID: 81045, + UserName: "lunny", + Content: "heart", + }, + { + UserID: 81045, + UserName: "lunny", + Content: "+1", + }, + }, }, }, prs) } From 6e4c2a230e04e47adc73edfe3d6706562c772a2f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 10 Jan 2020 21:06:05 +0800 Subject: [PATCH 4/9] update reactions when external user binding --- models/external_login_user.go | 6 +++++- models/issue.go | 19 ++++++++++++++++++- models/issue_comment.go | 8 ++++---- models/issue_reaction.go | 15 ++++++++++----- models/migrate.go | 1 + models/user.go | 9 +++++++++ routers/api/v1/repo/issue_reaction.go | 4 ++-- routers/repo/issue.go | 4 ++-- 8 files changed, 51 insertions(+), 15 deletions(-) diff --git a/models/external_login_user.go b/models/external_login_user.go index 265d855ccf0e6..6585e49fef5db 100644 --- a/models/external_login_user.go +++ b/models/external_login_user.go @@ -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) } diff --git a/models/issue.go b/models/issue.go index b6408365f7111..1c6b930d2e40e 100644 --- a/models/issue.go +++ b/models/issue.go @@ -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 } @@ -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 +} diff --git a/models/issue_comment.go b/models/issue_comment.go index 699b8f0487161..a2e19877469d7 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -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 } @@ -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) { diff --git a/models/issue_reaction.go b/models/issue_reaction.go index 74fa6db37dd4d..1592b4d341895 100644 --- a/models/issue_reaction.go +++ b/models/issue_reaction.go @@ -235,7 +235,7 @@ func (list ReactionList) HasUser(userID int64) bool { return false } for _, reaction := range list { - if reaction.UserID == userID { + if reaction.OriginalAuthor == "" && reaction.UserID == userID { return true } } @@ -254,6 +254,9 @@ 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{}{} } @@ -261,7 +264,7 @@ func (list ReactionList) getUserIDs() []int64 { 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 } @@ -276,7 +279,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() @@ -286,8 +291,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 diff --git a/models/migrate.go b/models/migrate.go index 61ea5b3cb4eaa..fd28fd156fb79 100644 --- a/models/migrate.go +++ b/models/migrate.go @@ -143,6 +143,7 @@ func InsertIssueComments(comments []*Comment) error { } for _, reaction := range comment.Reactions { + reaction.IssueID = comment.IssueID reaction.CommentID = comment.ID } if _, err := sess.Insert(comment.Reactions); err != nil { diff --git a/models/user.go b/models/user.go index ea1d110807565..d7129fb09a64c 100644 --- a/models/user.go +++ b/models/user.go @@ -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 { diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index b943ea6980abf..40632dcab70ad 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -65,7 +65,7 @@ func GetIssueCommentReactions(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err) return } - _, err = reactions.LoadUsers() + _, err = reactions.LoadUsers(ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err) return @@ -271,7 +271,7 @@ func GetIssueReactions(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err) return } - _, err = reactions.LoadUsers() + _, err = reactions.LoadUsers(ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err) return diff --git a/routers/repo/issue.go b/routers/repo/issue.go index afc115c6e2cc9..2fb42b0f22ccd 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -1608,7 +1608,7 @@ func ChangeCommentReaction(ctx *context.Context, form auth.ReactionForm) { } // Reload new reactions comment.Reactions = nil - if err = comment.LoadReactions(); err != nil { + if err = comment.LoadReactions(ctx.Repo.Repository); err != nil { log.Info("comment.LoadReactions: %s", err) break } @@ -1622,7 +1622,7 @@ func ChangeCommentReaction(ctx *context.Context, form auth.ReactionForm) { // Reload new reactions comment.Reactions = nil - if err = comment.LoadReactions(); err != nil { + if err = comment.LoadReactions(ctx.Repo.Repository); err != nil { log.Info("comment.LoadReactions: %s", err) break } From e7683db7095381af688620f01581606111f799e4 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 11 Jan 2020 12:11:47 +0800 Subject: [PATCH 5/9] Fix test --- models/issue_reaction_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/models/issue_reaction_test.go b/models/issue_reaction_test.go index 723a6be536848..e7aa45e4c3810 100644 --- a/models/issue_reaction_test.go +++ b/models/issue_reaction_test.go @@ -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) @@ -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) From 0e5aa4afe30131a801dadc0bed7d6f3cb3870773 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 11 Jan 2020 18:50:52 +0800 Subject: [PATCH 6/9] fix tests --- models/issue_reaction.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/issue_reaction.go b/models/issue_reaction.go index 1592b4d341895..944cbf535ba1d 100644 --- a/models/issue_reaction.go +++ b/models/issue_reaction.go @@ -22,7 +22,7 @@ type Reaction struct { 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"` + OriginalAuthorID int64 `xorm:"INDEX UNIQUE(s) NOT NULL DEFAULT(0)"` OriginalAuthor string User *User `xorm:"-"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` From 0e9740e18106f1a80174553e347753bfd3c20660 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 12 Jan 2020 18:30:25 +0800 Subject: [PATCH 7/9] change the copy head --- modules/migrations/base/reaction.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/migrations/base/reaction.go b/modules/migrations/base/reaction.go index ee751b3941613..b79223d4cd8e7 100644 --- a/modules/migrations/base/reaction.go +++ b/modules/migrations/base/reaction.go @@ -1,5 +1,4 @@ -// 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. From e2f7527d8ca8e263664d8d8fa34164ce1bf1ea12 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 12 Jan 2020 23:10:32 +0800 Subject: [PATCH 8/9] fix test --- models/issue_reaction.go | 2 +- modules/migrations/github_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/models/issue_reaction.go b/models/issue_reaction.go index 944cbf535ba1d..85a560e835eca 100644 --- a/models/issue_reaction.go +++ b/models/issue_reaction.go @@ -254,7 +254,7 @@ 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 == "" { + if reaction.OriginalAuthor != "" { continue } if _, ok := userIDs[reaction.UserID]; !ok { diff --git a/modules/migrations/github_test.go b/modules/migrations/github_test.go index db120580e8ba6..10943e4019a49 100644 --- a/modules/migrations/github_test.go +++ b/modules/migrations/github_test.go @@ -210,17 +210,17 @@ func TestGitHubDownloadRepo(t *testing.T) { { UserID: 1669571, UserName: "mrsdizzie", - Content: "confused", + Content: "-1", }, { UserID: 1669571, UserName: "mrsdizzie", - Content: "hooray", + Content: "confused", }, { UserID: 1669571, UserName: "mrsdizzie", - Content: "+1", + Content: "hooray", }, { UserID: 1669571, From 33495ce06880cf533fddc64899c9cf62567ea18f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 12 Jan 2020 23:19:17 +0800 Subject: [PATCH 9/9] fix migrator add/delete reaction --- models/issue_reaction.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/models/issue_reaction.go b/models/issue_reaction.go index 85a560e835eca..5c3bf9d06e876 100644 --- a/models/issue_reaction.go +++ b/models/issue_reaction.go @@ -51,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}) @@ -175,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 }