diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 0efcce30a..ee3dac362 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -246,6 +246,8 @@ var migrations = []Migration{ NewMigration("add timestamps to Star, Label, Follow, Watch and Collaboration", addTimeStamps), // v155 -> v156 NewMigration("add changed_protected_files column for pull_request table", addChangedProtectedFilesPullRequestColumn), + // v156 -> v157 + NewMigration("fix publisher ID for tag releases", fixPublisherIDforTagReleases), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v156.go b/models/migrations/v156.go new file mode 100644 index 000000000..dc9c20188 --- /dev/null +++ b/models/migrations/v156.go @@ -0,0 +1,140 @@ +// 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 ( + "fmt" + "path/filepath" + "strings" + + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" + + "xorm.io/xorm" +) + +// Copy paste from models/repo.go because we cannot import models package +func repoPath(userName, repoName string) string { + return filepath.Join(userPath(userName), strings.ToLower(repoName)+".git") +} + +func userPath(userName string) string { + return filepath.Join(setting.RepoRootPath, strings.ToLower(userName)) +} + +func fixPublisherIDforTagReleases(x *xorm.Engine) error { + + type Release struct { + ID int64 + RepoID int64 + Sha1 string + TagName string + PublisherID int64 + } + + type Repository struct { + ID int64 + OwnerID int64 + Name string + } + + type User struct { + ID int64 + Name string + Email string + } + + const batchSize = 100 + sess := x.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + return err + } + + var ( + gitRepoCache = make(map[int64]*git.Repository) + gitRepo *git.Repository + repoCache = make(map[int64]*Repository) + userCache = make(map[int64]*User) + ok bool + err error + ) + defer func() { + for i := range gitRepoCache { + gitRepoCache[i].Close() + } + }() + for start := 0; ; start += batchSize { + releases := make([]*Release, 0, batchSize) + + if err := sess.Limit(batchSize, start).Asc("id").Where("is_tag=?", true).Find(&releases); err != nil { + return err + } + + if len(releases) == 0 { + break + } + + for _, release := range releases { + gitRepo, ok = gitRepoCache[release.RepoID] + if !ok { + repo, ok := repoCache[release.RepoID] + if !ok { + repo = new(Repository) + has, err := sess.ID(release.RepoID).Get(repo) + if err != nil { + return err + } else if !has { + return fmt.Errorf("Repository %d is not exist", release.RepoID) + } + + repoCache[release.RepoID] = repo + } + + user, ok := userCache[repo.OwnerID] + if !ok { + user = new(User) + has, err := sess.ID(repo.OwnerID).Get(user) + if err != nil { + return err + } else if !has { + return fmt.Errorf("User %d is not exist", repo.OwnerID) + } + + userCache[repo.OwnerID] = user + } + + gitRepo, err = git.OpenRepository(repoPath(user.Name, repo.Name)) + if err != nil { + return err + } + gitRepoCache[release.RepoID] = gitRepo + } + + commit, err := gitRepo.GetTagCommit(release.TagName) + if err != nil { + return fmt.Errorf("GetTagCommit: %v", err) + } + + u := new(User) + exists, err := sess.Where("email=?", commit.Author.Email).Get(u) + if err != nil { + return err + } + + if !exists { + continue + } + + release.PublisherID = u.ID + if _, err := sess.ID(release.ID).Cols("publisher_id").Update(release); err != nil { + return err + } + } + } + + return sess.Commit() +} diff --git a/routers/repo/release.go b/routers/repo/release.go index ab251ec75..73c42ec7c 100644 --- a/routers/repo/release.go +++ b/routers/repo/release.go @@ -57,6 +57,7 @@ func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *models.Rel func Releases(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.releases") ctx.Data["PageIsReleaseList"] = true + ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch writeAccess := ctx.Repo.CanWrite(models.UnitTypeReleases) ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived diff --git a/services/release/release.go b/services/release/release.go index c36e2126e..af97987a2 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -58,6 +58,12 @@ func createTag(gitRepo *git.Repository, rel *models.Release) error { if err != nil { return fmt.Errorf("CommitsCount: %v", err) } + + u, err := models.GetUserByEmail(commit.Author.Email) + if err == nil { + rel.PublisherID = u.ID + } + } else { rel.CreatedUnix = timeutil.TimeStampNow() } diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index bba6f91e7..6ab2e4283 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -40,6 +40,15 @@

{{.TagName}}

+

+ {{ if gt .Publisher.ID 0 }} + + + {{.Publisher.Name}} + + {{ end }} + {{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}} {{$.i18n.Tr "repo.release.ahead.target" $.DefaultBranch}} +

{{if $.Permission.CanRead $.UnitTypeCode}} {{ShortSha .Sha1}}