You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

v156.go 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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. package migrations
  5. import (
  6. "fmt"
  7. "path/filepath"
  8. "strings"
  9. "code.gitea.io/gitea/modules/git"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/setting"
  12. "xorm.io/xorm"
  13. )
  14. // Copy paste from models/repo.go because we cannot import models package
  15. func repoPath(userName, repoName string) string {
  16. return filepath.Join(userPath(userName), strings.ToLower(repoName)+".git")
  17. }
  18. func userPath(userName string) string {
  19. return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
  20. }
  21. func fixPublisherIDforTagReleases(x *xorm.Engine) error {
  22. type Release struct {
  23. ID int64
  24. RepoID int64
  25. Sha1 string
  26. TagName string
  27. PublisherID int64
  28. }
  29. type Repository struct {
  30. ID int64
  31. OwnerID int64
  32. OwnerName string
  33. Name string
  34. }
  35. type User struct {
  36. ID int64
  37. Name string
  38. Email string
  39. }
  40. const batchSize = 100
  41. sess := x.NewSession()
  42. defer sess.Close()
  43. var (
  44. repo *Repository
  45. gitRepo *git.Repository
  46. user *User
  47. )
  48. defer func() {
  49. if gitRepo != nil {
  50. gitRepo.Close()
  51. }
  52. }()
  53. for start := 0; ; start += batchSize {
  54. releases := make([]*Release, 0, batchSize)
  55. if err := sess.Begin(); err != nil {
  56. return err
  57. }
  58. if err := sess.Limit(batchSize, start).
  59. Where("publisher_id = 0 OR publisher_id is null").
  60. Asc("repo_id", "id").Where("is_tag=?", true).
  61. Find(&releases); err != nil {
  62. return err
  63. }
  64. if len(releases) == 0 {
  65. break
  66. }
  67. for _, release := range releases {
  68. if repo == nil || repo.ID != release.RepoID {
  69. if gitRepo != nil {
  70. gitRepo.Close()
  71. gitRepo = nil
  72. }
  73. repo = new(Repository)
  74. has, err := sess.ID(release.RepoID).Get(repo)
  75. if err != nil {
  76. log.Error("Error whilst loading repository[%d] for release[%d] with tag name %s", release.RepoID, release.ID, release.TagName)
  77. return err
  78. } else if !has {
  79. log.Warn("Release[%d] is orphaned and refers to non-existing repository %d", release.ID, release.RepoID)
  80. log.Warn("This release should be deleted")
  81. continue
  82. }
  83. if repo.OwnerName == "" {
  84. // v120.go migration may not have been run correctly - we'll just replicate it here
  85. // because this appears to be a common-ish problem.
  86. if _, err := sess.Exec("UPDATE repository SET owner_name = (SELECT name FROM `user` WHERE `user`.id = repository.owner_id)"); err != nil {
  87. log.Error("Error whilst updating repository[%d] owner name", repo.ID)
  88. return err
  89. }
  90. if _, err := sess.ID(release.RepoID).Get(repo); err != nil {
  91. log.Error("Error whilst loading repository[%d] for release[%d] with tag name %s", release.RepoID, release.ID, release.TagName)
  92. return err
  93. }
  94. }
  95. gitRepo, err = git.OpenRepository(repoPath(repo.OwnerName, repo.Name))
  96. if err != nil {
  97. log.Error("Error whilst opening git repo for %-v", repo)
  98. return err
  99. }
  100. }
  101. commit, err := gitRepo.GetTagCommit(release.TagName)
  102. if err != nil {
  103. if git.IsErrNotExist(err) {
  104. log.Warn("Unable to find commit %s for Tag: %s in %-v. Cannot update publisher ID.", err.(*git.ErrNotExist).ID, release.TagName, repo)
  105. continue
  106. }
  107. log.Error("Error whilst getting commit for Tag: %s in %-v.", release.TagName, repo)
  108. return fmt.Errorf("GetTagCommit: %v", err)
  109. }
  110. if user == nil || !strings.EqualFold(user.Email, commit.Author.Email) {
  111. user = new(User)
  112. _, err = sess.Where("email=?", commit.Author.Email).Get(user)
  113. if err != nil {
  114. log.Error("Error whilst getting commit author by email: %s for Tag: %s in %-v.", commit.Author.Email, release.TagName, repo)
  115. return err
  116. }
  117. user.Email = commit.Author.Email
  118. }
  119. if user.ID <= 0 {
  120. continue
  121. }
  122. release.PublisherID = user.ID
  123. if _, err := sess.ID(release.ID).Cols("publisher_id").Update(release); err != nil {
  124. log.Error("Error whilst updating publisher[%d] for release[%d] with tag name %s", release.PublisherID, release.ID, release.TagName)
  125. return err
  126. }
  127. }
  128. if gitRepo != nil {
  129. gitRepo.Close()
  130. }
  131. if err := sess.Commit(); err != nil {
  132. return err
  133. }
  134. }
  135. return nil
  136. }