From 1f1ecda541d7f526c004e7bfabab814dbc84dc2c Mon Sep 17 00:00:00 2001 From: mrsdizzie Date: Sun, 7 Jul 2019 22:14:12 -0400 Subject: [PATCH] Display original author and URL information when showing migrated issues/comments (#7352) * Store original author info for migrated issues and comments Keep original author name for displaying in Gitea interface and also store original author user ID for potential future use in linking accounts from old location. * Add original_url for repo Store the original URL for a migrated repo Clean up migrations/tests * fix migration * fix golangci-lint * make 'make revive' happy also * Modify templates to use OriginalAuthor if set Use the original author name in templates if it is set rather than the user who migrated/currently owns the issues * formatting fixes * make generate-swagger * Use default avatar for imported comments * Remove no longer used IgnoreIssueAuthor option * Add OriginalAuthorID to swagger also --- models/issue.go | 44 ++++++------- models/issue_comment.go | 6 +- models/migrations/migrations.go | 2 + models/migrations/v89.go | 36 +++++++++++ models/repo.go | 15 +++++ modules/migrations/base/comment.go | 1 + modules/migrations/base/issue.go | 1 + modules/migrations/base/options.go | 20 +++--- modules/migrations/base/pullrequest.go | 1 + modules/migrations/base/repo.go | 1 + modules/migrations/gitea.go | 63 ++++++++++--------- modules/migrations/gitea_test.go | 19 +++--- modules/migrations/github.go | 5 +- modules/migrations/github_test.go | 10 +++ modules/migrations/migrate.go | 23 +------ modules/structs/issue.go | 22 ++++--- modules/structs/issue_comment.go | 14 +++-- modules/structs/repo.go | 1 + modules/templates/helper.go | 11 ++++ options/locale/locale_en-US.ini | 2 + public/css/index.css | 3 + public/less/_base.less | 12 ++++ templates/repo/issue/list.tmpl | 5 +- templates/repo/issue/view_content.tmpl | 8 +++ .../repo/issue/view_content/comments.tmpl | 8 +++ templates/repo/issue/view_title.tmpl | 22 +++++-- templates/swagger/v1_json.tmpl | 22 +++++++ templates/user/dashboard/issues.tmpl | 4 +- 28 files changed, 263 insertions(+), 118 deletions(-) create mode 100644 models/migrations/v89.go diff --git a/models/issue.go b/models/issue.go index b5504beb71b..63074cd40ce 100644 --- a/models/issue.go +++ b/models/issue.go @@ -25,27 +25,29 @@ import ( // Issue represents an issue or pull request of repository. type Issue struct { - ID int64 `xorm:"pk autoincr"` - RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"` - Repo *Repository `xorm:"-"` - Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository. - PosterID int64 `xorm:"INDEX"` - Poster *User `xorm:"-"` - Title string `xorm:"name"` - Content string `xorm:"TEXT"` - RenderedContent string `xorm:"-"` - Labels []*Label `xorm:"-"` - MilestoneID int64 `xorm:"INDEX"` - Milestone *Milestone `xorm:"-"` - Priority int - AssigneeID int64 `xorm:"-"` - Assignee *User `xorm:"-"` - IsClosed bool `xorm:"INDEX"` - IsRead bool `xorm:"-"` - IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not. - PullRequest *PullRequest `xorm:"-"` - NumComments int - Ref string + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"` + Repo *Repository `xorm:"-"` + Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository. + PosterID int64 `xorm:"INDEX"` + Poster *User `xorm:"-"` + OriginalAuthor string + OriginalAuthorID int64 + Title string `xorm:"name"` + Content string `xorm:"TEXT"` + RenderedContent string `xorm:"-"` + Labels []*Label `xorm:"-"` + MilestoneID int64 `xorm:"INDEX"` + Milestone *Milestone `xorm:"-"` + Priority int + AssigneeID int64 `xorm:"-"` + Assignee *User `xorm:"-"` + IsClosed bool `xorm:"INDEX"` + IsRead bool `xorm:"-"` + IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not. + PullRequest *PullRequest `xorm:"-"` + NumComments int + Ref string DeadlineUnix util.TimeStamp `xorm:"INDEX"` diff --git a/models/issue_comment.go b/models/issue_comment.go index c9f1bd9d5f2..b930b0b12a2 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -101,8 +101,10 @@ const ( type Comment struct { ID int64 `xorm:"pk autoincr"` Type CommentType - PosterID int64 `xorm:"INDEX"` - Poster *User `xorm:"-"` + PosterID int64 `xorm:"INDEX"` + Poster *User `xorm:"-"` + OriginalAuthor string + OriginalAuthorID int64 IssueID int64 `xorm:"INDEX"` Issue *Issue `xorm:"-"` LabelID int64 diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index ef43b0453b0..62fadf5f361 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -232,6 +232,8 @@ var migrations = []Migration{ NewMigration("add avatar field to repository", addAvatarFieldToRepository), // v88 -> v89 NewMigration("add commit status context field to commit_status", addCommitStatusContext), + // v89 -> v90 + NewMigration("add original author/url migration info to issues, comments, and repo ", addOriginalMigrationInfo), } // Migrate database to current version diff --git a/models/migrations/v89.go b/models/migrations/v89.go new file mode 100644 index 00000000000..83d0b1a8b9f --- /dev/null +++ b/models/migrations/v89.go @@ -0,0 +1,36 @@ +// Copyright 2019 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 "github.com/go-xorm/xorm" + +func addOriginalMigrationInfo(x *xorm.Engine) error { + // Issue see models/issue.go + type Issue struct { + OriginalAuthor string + OriginalAuthorID int64 + } + + if err := x.Sync2(new(Issue)); err != nil { + return err + } + + // Issue see models/issue_comment.go + type Comment struct { + OriginalAuthor string + OriginalAuthorID int64 + } + + if err := x.Sync2(new(Comment)); err != nil { + return err + } + + // Issue see models/repo.go + type Repository struct { + OriginalURL string + } + + return x.Sync2(new(Repository)) +} diff --git a/models/repo.go b/models/repo.go index 59ce18fa88e..9bedeba952f 100644 --- a/models/repo.go +++ b/models/repo.go @@ -136,6 +136,7 @@ type Repository struct { Name string `xorm:"INDEX NOT NULL"` Description string Website string + OriginalURL string DefaultBranch string NumWatches int @@ -847,6 +848,7 @@ func (repo *Repository) CloneLink() (cl *CloneLink) { type MigrateRepoOptions struct { Name string Description string + OriginalURL string IsPrivate bool IsMirror bool RemoteAddr string @@ -878,6 +880,7 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err repo, err := CreateRepository(doer, u, CreateRepoOptions{ Name: opts.Name, Description: opts.Description, + OriginalURL: opts.OriginalURL, IsPrivate: opts.IsPrivate, IsMirror: opts.IsMirror, }) @@ -1092,6 +1095,7 @@ func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { type CreateRepoOptions struct { Name string Description string + OriginalURL string Gitignores string License string Readme string @@ -1358,6 +1362,7 @@ func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err Name: opts.Name, LowerName: strings.ToLower(opts.Name), Description: opts.Description, + OriginalURL: opts.OriginalURL, IsPrivate: opts.IsPrivate, IsFsckEnabled: !opts.IsMirror, CloseIssuesViaCommitInAnyBranch: setting.Repository.DefaultCloseIssuesViaCommitsInAnyBranch, @@ -2678,3 +2683,13 @@ func (repo *Repository) DeleteAvatar() error { } return sess.Commit() } + +// GetOriginalURLHostname returns the hostname of a URL or the URL +func (repo *Repository) GetOriginalURLHostname() string { + u, err := url.Parse(repo.OriginalURL) + if err != nil { + return repo.OriginalURL + } + + return u.Host +} diff --git a/modules/migrations/base/comment.go b/modules/migrations/base/comment.go index d89ec3a3f5a..38c544d6e04 100644 --- a/modules/migrations/base/comment.go +++ b/modules/migrations/base/comment.go @@ -10,6 +10,7 @@ import "time" // Comment is a standard comment information type Comment struct { IssueIndex int64 + PosterID int64 PosterName string PosterEmail string Created time.Time diff --git a/modules/migrations/base/issue.go b/modules/migrations/base/issue.go index ddadd0c2b3d..08d947b05d3 100644 --- a/modules/migrations/base/issue.go +++ b/modules/migrations/base/issue.go @@ -10,6 +10,7 @@ import "time" // Issue is a standard issue information type Issue struct { Number int64 + PosterID int64 PosterName string PosterEmail string Title string diff --git a/modules/migrations/base/options.go b/modules/migrations/base/options.go index 262981b9332..ba7fdc68156 100644 --- a/modules/migrations/base/options.go +++ b/modules/migrations/base/options.go @@ -12,15 +12,15 @@ type MigrateOptions struct { AuthPassword string Name string Description string + OriginalURL string - Wiki bool - Issues bool - Milestones bool - Labels bool - Releases bool - Comments bool - PullRequests bool - Private bool - Mirror bool - IgnoreIssueAuthor bool // if true will not add original author information before issues or comments content. + Wiki bool + Issues bool + Milestones bool + Labels bool + Releases bool + Comments bool + PullRequests bool + Private bool + Mirror bool } diff --git a/modules/migrations/base/pullrequest.go b/modules/migrations/base/pullrequest.go index 515cab3f919..42456fd3141 100644 --- a/modules/migrations/base/pullrequest.go +++ b/modules/migrations/base/pullrequest.go @@ -15,6 +15,7 @@ type PullRequest struct { Number int64 Title string PosterName string + PosterID int64 PosterEmail string Content string Milestone string diff --git a/modules/migrations/base/repo.go b/modules/migrations/base/repo.go index 907d8fc09e7..5cfb0de920d 100644 --- a/modules/migrations/base/repo.go +++ b/modules/migrations/base/repo.go @@ -15,4 +15,5 @@ type Repository struct { AuthUsername string AuthPassword string CloneURL string + OriginalURL string } diff --git a/modules/migrations/gitea.go b/modules/migrations/gitea.go index 1df824c94f1..b15aed5f4be 100644 --- a/modules/migrations/gitea.go +++ b/modules/migrations/gitea.go @@ -82,6 +82,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate r, err := models.MigrateRepository(g.doer, owner, models.MigrateRepoOptions{ Name: g.repoName, Description: repo.Description, + OriginalURL: repo.OriginalURL, IsMirror: repo.IsMirror, RemoteAddr: repo.CloneURL, IsPrivate: repo.IsPrivate, @@ -247,17 +248,19 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error { } var is = models.Issue{ - RepoID: g.repo.ID, - Repo: g.repo, - Index: issue.Number, - PosterID: g.doer.ID, - Title: issue.Title, - Content: issue.Content, - IsClosed: issue.State == "closed", - IsLocked: issue.IsLocked, - MilestoneID: milestoneID, - Labels: labels, - CreatedUnix: util.TimeStamp(issue.Created.Unix()), + RepoID: g.repo.ID, + Repo: g.repo, + Index: issue.Number, + PosterID: g.doer.ID, + OriginalAuthor: issue.PosterName, + OriginalAuthorID: issue.PosterID, + Title: issue.Title, + Content: issue.Content, + IsClosed: issue.State == "closed", + IsLocked: issue.IsLocked, + MilestoneID: milestoneID, + Labels: labels, + CreatedUnix: util.TimeStamp(issue.Created.Unix()), } if issue.Closed != nil { is.ClosedUnix = util.TimeStamp(issue.Closed.Unix()) @@ -293,11 +296,13 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error { } cms = append(cms, &models.Comment{ - IssueID: issueID, - Type: models.CommentTypeComment, - PosterID: g.doer.ID, - Content: comment.Content, - CreatedUnix: util.TimeStamp(comment.Created.Unix()), + IssueID: issueID, + Type: models.CommentTypeComment, + PosterID: g.doer.ID, + OriginalAuthor: comment.PosterName, + OriginalAuthorID: comment.PosterID, + Content: comment.Content, + CreatedUnix: util.TimeStamp(comment.Created.Unix()), }) // TODO: Reactions @@ -430,18 +435,20 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*models.PullR HasMerged: pr.Merged, Issue: &models.Issue{ - RepoID: g.repo.ID, - Repo: g.repo, - Title: pr.Title, - Index: pr.Number, - PosterID: g.doer.ID, - Content: pr.Content, - MilestoneID: milestoneID, - IsPull: true, - IsClosed: pr.State == "closed", - IsLocked: pr.IsLocked, - Labels: labels, - CreatedUnix: util.TimeStamp(pr.Created.Unix()), + RepoID: g.repo.ID, + Repo: g.repo, + Title: pr.Title, + Index: pr.Number, + PosterID: g.doer.ID, + OriginalAuthor: pr.PosterName, + OriginalAuthorID: pr.PosterID, + Content: pr.Content, + MilestoneID: milestoneID, + IsPull: true, + IsClosed: pr.State == "closed", + IsLocked: pr.IsLocked, + Labels: labels, + CreatedUnix: util.TimeStamp(pr.Created.Unix()), }, } diff --git a/modules/migrations/gitea_test.go b/modules/migrations/gitea_test.go index 22da7da171a..88a3a6d2189 100644 --- a/modules/migrations/gitea_test.go +++ b/modules/migrations/gitea_test.go @@ -34,16 +34,15 @@ func TestGiteaUploadRepo(t *testing.T) { Name: repoName, AuthUsername: "", - Wiki: true, - Issues: true, - Milestones: true, - Labels: true, - Releases: true, - Comments: true, - PullRequests: true, - Private: true, - Mirror: false, - IgnoreIssueAuthor: false, + Wiki: true, + Issues: true, + Milestones: true, + Labels: true, + Releases: true, + Comments: true, + PullRequests: true, + Private: true, + Mirror: false, }) assert.NoError(t, err) diff --git a/modules/migrations/github.go b/modules/migrations/github.go index e6b532df9c5..93ba1085481 100644 --- a/modules/migrations/github.go +++ b/modules/migrations/github.go @@ -107,13 +107,13 @@ func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) { if err != nil { return nil, err } - // convert github repo to stand Repo return &base.Repository{ Owner: g.repoOwner, Name: gr.GetName(), IsPrivate: *gr.Private, Description: gr.GetDescription(), + OriginalURL: gr.GetHTMLURL(), CloneURL: gr.GetCloneURL(), }, nil } @@ -317,6 +317,7 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool, allIssues = append(allIssues, &base.Issue{ Title: *issue.Title, Number: int64(*issue.Number), + PosterID: *issue.User.ID, PosterName: *issue.User.Login, PosterEmail: email, Content: body, @@ -359,6 +360,7 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er } allComments = append(allComments, &base.Comment{ IssueIndex: issueNumber, + PosterID: *comment.User.ID, PosterName: *comment.User.Login, PosterEmail: email, Content: *comment.Body, @@ -451,6 +453,7 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq Title: *pr.Title, Number: int64(*pr.Number), PosterName: *pr.User.Login, + PosterID: *pr.User.ID, PosterEmail: email, Content: body, Milestone: milestone, diff --git a/modules/migrations/github_test.go b/modules/migrations/github_test.go index 700183bdc1a..0f52a62eb25 100644 --- a/modules/migrations/github_test.go +++ b/modules/migrations/github_test.go @@ -68,6 +68,7 @@ func TestGitHubDownloadRepo(t *testing.T) { Owner: "go-gitea", Description: "Git with a cup of tea, painless self-hosted git service", CloneURL: "https://github.com/go-gitea/gitea.git", + OriginalURL: "https://github.com/go-gitea/gitea", }, repo) milestones, err := downloader.GetMilestones() @@ -180,6 +181,7 @@ func TestGitHubDownloadRepo(t *testing.T) { Title: "Contribution system: History heatmap for user", Content: "Hi guys,\r\n\r\nI think that is a possible feature, a history heatmap similar to github or gitlab.\r\nActually exists a plugin called Calendar HeatMap. I used this on mine project to heat application log and worked fine here.\r\nThen, is only a idea, what you think? :)\r\n\r\nhttp://cal-heatmap.com/\r\nhttps://github.com/wa0x6e/cal-heatmap\r\n\r\nReference: https://github.com/gogits/gogs/issues/1640", Milestone: "1.7.0", + PosterID: 1520407, PosterName: "joubertredrat", State: "closed", Created: time.Date(2016, 11, 02, 18, 51, 55, 0, time.UTC), @@ -209,6 +211,7 @@ func TestGitHubDownloadRepo(t *testing.T) { Title: "display page revisions on wiki", Content: "Hi guys,\r\n\r\nWiki on Gogs is very fine, I liked a lot, but I think that is good idea to be possible see other revisions from page as a page history.\r\n\r\nWhat you think?\r\n\r\nReference: https://github.com/gogits/gogs/issues/2991", Milestone: "1.x.x", + PosterID: 1520407, PosterName: "joubertredrat", State: "open", Created: time.Date(2016, 11, 02, 18, 57, 32, 0, time.UTC), @@ -238,6 +241,7 @@ func TestGitHubDownloadRepo(t *testing.T) { Title: "audit logs", Content: "Hi,\r\n\r\nI think that is good idea to have user operation log to admin see what the user is doing at Gogs. Similar to example below\r\n\r\n| user | operation | information |\r\n| --- | --- | --- |\r\n| joubertredrat | repo.create | Create repo MyProjectData |\r\n| joubertredrat | user.settings | Edit settings |\r\n| tboerger | repo.fork | Create Fork from MyProjectData to ForkMyProjectData |\r\n| bkcsoft | repo.remove | Remove repo MySource |\r\n| tboerger | admin.auth | Edit auth LDAP org-connection |\r\n\r\nThis resource can be used on user page too, as user activity, set that log row is public (repo._) or private (user._, admin.*) and display only public activity.\r\n\r\nWhat you think?\r\n\r\n[Chat summary from March 14, 2017](https://github.com/go-gitea/gitea/issues/8#issuecomment-286463807)\r\n\r\nReferences:\r\nhttps://github.com/gogits/gogs/issues/3016", Milestone: "1.x.x", + PosterID: 1520407, PosterName: "joubertredrat", State: "open", Created: time.Date(2016, 11, 02, 18, 59, 20, 0, time.UTC), @@ -270,6 +274,7 @@ func TestGitHubDownloadRepo(t *testing.T) { assert.EqualValues(t, []*base.Comment{ { IssueIndex: 6, + PosterID: 4726179, PosterName: "bkcsoft", Created: time.Date(2016, 11, 02, 18, 59, 48, 0, time.UTC), Content: `I would prefer a solution that is in the backend, unless it's required to have it update without reloading. Unfortunately I can't seem to find anything that does that :unamused: @@ -288,6 +293,7 @@ Also this would _require_ caching, since it will fetch huge amounts of data from }, { IssueIndex: 6, + PosterID: 1520407, PosterName: "joubertredrat", Created: time.Date(2016, 11, 02, 19, 16, 56, 0, time.UTC), Content: `Yes, this plugin build on front-end, with backend I don't know too, but we can consider make component for this. @@ -306,6 +312,7 @@ In my case I use ajax to get data, but build on frontend anyway }, { IssueIndex: 6, + PosterID: 1799009, PosterName: "xinity", Created: time.Date(2016, 11, 03, 13, 04, 56, 0, time.UTC), Content: `following @bkcsoft retention strategy in cache is a must if we don't want gitea to waste ressources. @@ -345,6 +352,7 @@ something like in the latest 15days could be enough don't you think ? Title: "Rename import paths: \"github.com/gogits/gogs\" -> \"github.com/go-gitea/gitea\"", Content: "", Milestone: "1.0.0", + PosterID: 7011819, PosterName: "andreynering", State: "closed", Created: time.Date(2016, 11, 02, 17, 01, 19, 0, time.UTC), @@ -380,6 +388,7 @@ something like in the latest 15days could be enough don't you think ? Title: "Fix sender of issue notifications", Content: "It is the FROM field in mailer configuration that needs be used,\r\nnot the USER field, which is for authentication.\r\n\r\nMigrated from https://github.com/gogits/gogs/pull/3616\r\n", Milestone: "1.0.0", + PosterID: 289678, PosterName: "strk", State: "closed", Created: time.Date(2016, 11, 02, 17, 24, 19, 0, time.UTC), @@ -417,6 +426,7 @@ something like in the latest 15days could be enough don't you think ? Title: "Use proper url for libravatar dep", Content: "Fetch go-libravatar from its official source, rather than from an unmaintained fork\r\n", Milestone: "1.0.0", + PosterID: 289678, PosterName: "strk", State: "closed", Created: time.Date(2016, 11, 02, 17, 34, 31, 0, time.UTC), diff --git a/modules/migrations/migrate.go b/modules/migrations/migrate.go index 7fc7911f218..a86614c3172 100644 --- a/modules/migrations/migrate.go +++ b/modules/migrations/migrate.go @@ -6,8 +6,6 @@ package migrations import ( - "fmt" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/migrations/base" @@ -155,11 +153,6 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts if err != nil { return err } - for _, issue := range issues { - if !opts.IgnoreIssueAuthor { - issue.Content = fmt.Sprintf("Author: @%s \n\n%s", issue.PosterName, issue.Content) - } - } if err := uploader.CreateIssues(issues...); err != nil { return err @@ -175,11 +168,7 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts if err != nil { return err } - for _, comment := range comments { - if !opts.IgnoreIssueAuthor { - comment.Content = fmt.Sprintf("Author: @%s \n\n%s", comment.PosterName, comment.Content) - } - } + allComments = append(allComments, comments...) if len(allComments) >= commentBatchSize { @@ -212,11 +201,6 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts return err } - for _, pr := range prs { - if !opts.IgnoreIssueAuthor { - pr.Content = fmt.Sprintf("Author: @%s \n\n%s", pr.PosterName, pr.Content) - } - } if err := uploader.CreatePullRequests(prs...); err != nil { return err } @@ -231,11 +215,6 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts if err != nil { return err } - for _, comment := range comments { - if !opts.IgnoreIssueAuthor { - comment.Content = fmt.Sprintf("Author: @%s \n\n%s", comment.PosterName, comment.Content) - } - } allComments = append(allComments, comments...) diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 6d7517bdc7b..58fd7344b4f 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -29,16 +29,18 @@ type PullRequestMeta struct { // Issue represents an issue in a repository // swagger:model type Issue struct { - ID int64 `json:"id"` - URL string `json:"url"` - Index int64 `json:"number"` - Poster *User `json:"user"` - Title string `json:"title"` - Body string `json:"body"` - Labels []*Label `json:"labels"` - Milestone *Milestone `json:"milestone"` - Assignee *User `json:"assignee"` - Assignees []*User `json:"assignees"` + ID int64 `json:"id"` + URL string `json:"url"` + Index int64 `json:"number"` + Poster *User `json:"user"` + OriginalAuthor string `json:"original_author"` + OriginalAuthorID int64 `json:"original_author_id"` + Title string `json:"title"` + Body string `json:"body"` + Labels []*Label `json:"labels"` + Milestone *Milestone `json:"milestone"` + Assignee *User `json:"assignee"` + Assignees []*User `json:"assignees"` // Whether the issue is open or closed // // type: string diff --git a/modules/structs/issue_comment.go b/modules/structs/issue_comment.go index 185f3910ed4..0c8ac20017f 100644 --- a/modules/structs/issue_comment.go +++ b/modules/structs/issue_comment.go @@ -10,12 +10,14 @@ import ( // Comment represents a comment on a commit or issue type Comment struct { - ID int64 `json:"id"` - HTMLURL string `json:"html_url"` - PRURL string `json:"pull_request_url"` - IssueURL string `json:"issue_url"` - Poster *User `json:"user"` - Body string `json:"body"` + ID int64 `json:"id"` + HTMLURL string `json:"html_url"` + PRURL string `json:"pull_request_url"` + IssueURL string `json:"issue_url"` + Poster *User `json:"user"` + OriginalAuthor string `json:"original_author"` + OriginalAuthorID int64 `json:"original_author_id"` + Body string `json:"body"` // swagger:strfmt date-time Created time.Time `json:"created_at"` // swagger:strfmt date-time diff --git a/modules/structs/repo.go b/modules/structs/repo.go index b4d162b776f..81203319e01 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -31,6 +31,7 @@ type Repository struct { HTMLURL string `json:"html_url"` SSHURL string `json:"ssh_url"` CloneURL string `json:"clone_url"` + OriginalURL string `json:"original_url"` Website string `json:"website"` Stars int `json:"stars_count"` Forks int `json:"forks_count"` diff --git a/modules/templates/helper.go b/modules/templates/helper.go index c4551bb4be4..5a3969c098f 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -82,6 +82,7 @@ func NewFuncMap() []template.FuncMap { "FileSize": base.FileSize, "Subtract": base.Subtract, "EntryIcon": base.EntryIcon, + "MigrationIcon": MigrationIcon, "Add": func(a, b int) int { return a + b }, @@ -540,3 +541,13 @@ func TrN(lang string, cnt interface{}, key1, keyN string) string { } return keyN } + +// MigrationIcon returns a Font Awesome name matching the service an issue/comment was migrated from +func MigrationIcon(hostname string) string { + switch hostname { + case "github.com": + return "fa-github" + default: + return "fa-git-alt" + } +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 223df91fda4..0c83a7aef17 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -621,6 +621,8 @@ migrate.invalid_local_path = "The local path is invalid. It does not exist or is migrate.failed = Migration failed: %v migrate.lfs_mirror_unsupported = Mirroring LFS objects is not supported - use 'git lfs fetch --all' and 'git lfs push --all' instead. migrate.migrate_items_options = When migrating from github, input a username and migration options will be displayed. +migrated_from = Migrated from %[2]s +migrated_from_fake = Migrated From %[1]s mirror_from = mirror of forked_from = forked from diff --git a/public/css/index.css b/public/css/index.css index 437605e1d31..9039409f146 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -137,6 +137,9 @@ a{cursor:pointer} .ui .background.purple{background-color:#6e5494!important} .ui .background.yellow{background-color:#fbbf09!important} .ui .background.gold{background-color:#a1882b!important} +.ui .migrate{color:#888!important;opacity:.5} +.ui .migrate a{color:#444!important} +.ui .migrate a:hover{color:#000!important} .ui .branch-tag-choice{line-height:20px} @media only screen and (max-width:767px){.ui.pagination.menu .item.navigation span.navigation_label,.ui.pagination.menu .item:not(.active):not(.navigation){display:none} } diff --git a/public/less/_base.less b/public/less/_base.less index 4ce1b8eff9f..aae3b97c725 100644 --- a/public/less/_base.less +++ b/public/less/_base.less @@ -588,6 +588,18 @@ code, } } + .migrate { + color: #888888 !important; + opacity: 0.5; + a { + color: #444444 !important; + + &:hover { + color: #000000 !important; + } + } + } + .branch-tag-choice { line-height: 20px; } diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 3007c991061..45b2cc67e37 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -234,8 +234,9 @@

{{ $timeStr := TimeSinceUnix .GetLastEventTimestamp $.Lang }} - - {{if gt .Poster.ID 0}} + {{if .OriginalAuthor }} + {{$.i18n.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor | Safe}} + {{else if gt .Poster.ID 0}} {{$.i18n.Tr .GetLastEventLabel $timeStr .Poster.HomeLink (.Poster.GetDisplayName | Escape) | Safe}} {{else}} {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}} diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl index 16700a8dc19..b3f88c662d9 100644 --- a/templates/repo/issue/view_content.tmpl +++ b/templates/repo/issue/view_content.tmpl @@ -12,12 +12,20 @@

+ {{if .Issue.OriginalAuthor }} + + {{else}} + {{end}}
+ {{if .Issue.OriginalAuthor }} + {{ .Issue.OriginalAuthor }} {{.i18n.Tr "repo.issues.commented_at" .Issue.HashTag $createdStr | Safe}} {{if .Repository.OriginalURL}} ({{$.i18n.Tr "repo.migrated_from" .Repository.OriginalURL .Repository.GetOriginalURLHostname | Safe }}){{end}} + {{else}} {{.Issue.Poster.GetDisplayName}} {{.i18n.Tr "repo.issues.commented_at" .Issue.HashTag $createdStr | Safe}} + {{end}} {{if not $.Repository.IsArchived}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) }} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 20474f63020..68303cf1ca2 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -9,12 +9,20 @@ 22 = REVIEW, 23 = ISSUE_LOCKED, 24 = ISSUE_UNLOCKED --> {{if eq .Type 0}}
+ {{if .OriginalAuthor }} + + {{else}} + {{end}}
+ {{if .OriginalAuthor }} + {{ .OriginalAuthor }} {{$.i18n.Tr "repo.issues.commented_at" .Issue.HashTag $createdStr | Safe}} {{if $.Repository.OriginalURL}}({{$.i18n.Tr "repo.migrated_from" $.Repository.OriginalURL $.Repository.GetOriginalURLHostname | Safe }}){{end}} + {{else}} {{.Poster.GetDisplayName}} {{$.i18n.Tr "repo.issues.commented_at" .HashTag $createdStr | Safe}} + {{end}} {{if not $.Repository.IsArchived}}
{{if gt .ShowTag 0}} diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl index 78c892fa4d5..4b254d2c4b4 100644 --- a/templates/repo/issue/view_title.tmpl +++ b/templates/repo/issue/view_title.tmpl @@ -27,16 +27,28 @@ {{if .Issue.IsPull}} {{if .Issue.PullRequest.HasMerged}} {{ $mergedStr:= TimeSinceUnix .Issue.PullRequest.MergedUnix $.Lang }} - {{.Issue.PullRequest.Merger.GetDisplayName}} - {{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Str2html}} + {{if .Issue.OriginalAuthor }} + {{.Issue.OriginalAuthor}} + {{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Str2html}} + {{else}} + {{.Issue.PullRequest.Merger.GetDisplayName}} + {{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Str2html}} + {{end}} {{else}} - {{.Issue.Poster.GetDisplayName}} - {{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}} + {{if .Issue.OriginalAuthor }} + {{.Issue.OriginalAuthor}} + {{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}} + {{else}} + {{.Issue.Poster.GetDisplayName}} + {{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}} + {{end}} {{end}} {{else}} {{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.Lang }} - {{if gt .Issue.Poster.ID 0}} + {{if .Issue.OriginalAuthor }} + {{$.i18n.Tr "repo.issues.opened_by_fake" $createdStr .Issue.OriginalAuthor | Safe}} + {{else if gt .Issue.Poster.ID 0}} {{$.i18n.Tr "repo.issues.opened_by" $createdStr .Issue.Poster.HomeLink (.Issue.Poster.GetDisplayName|Escape) | Safe}} {{else}} {{$.i18n.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.Poster.GetDisplayName|Escape) | Safe}} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d6d501ed22c..11f41611726 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -6971,6 +6971,15 @@ "type": "string", "x-go-name": "IssueURL" }, + "original_author": { + "type": "string", + "x-go-name": "OriginalAuthor" + }, + "original_author_id": { + "type": "integer", + "format": "int64", + "x-go-name": "OriginalAuthorID" + }, "pull_request_url": { "type": "string", "x-go-name": "PRURL" @@ -8669,6 +8678,15 @@ "format": "int64", "x-go-name": "Index" }, + "original_author": { + "type": "string", + "x-go-name": "OriginalAuthor" + }, + "original_author_id": { + "type": "integer", + "format": "int64", + "x-go-name": "OriginalAuthorID" + }, "pull_request": { "$ref": "#/definitions/PullRequestMeta" }, @@ -9489,6 +9507,10 @@ "format": "int64", "x-go-name": "OpenIssues" }, + "original_url": { + "type": "string", + "x-go-name": "OriginalURL" + }, "owner": { "$ref": "#/definitions/User" }, diff --git a/templates/user/dashboard/issues.tmpl b/templates/user/dashboard/issues.tmpl index b69509d7992..7083569164f 100644 --- a/templates/user/dashboard/issues.tmpl +++ b/templates/user/dashboard/issues.tmpl @@ -93,7 +93,9 @@ {{end}}

- {{if gt .Poster.ID 0}} + {{if .OriginalAuthor}} + {{$.i18n.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor | Safe}} + {{else if gt .Poster.ID 0}} {{$.i18n.Tr .GetLastEventLabel $timeStr .Poster.HomeLink (.Poster.GetDisplayName|Escape) | Safe}} {{else}} {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName|Escape) | Safe}}