|
| 1 | +// Copyright 2019 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 | + "fmt" |
| 9 | + |
| 10 | + "code.gitea.io/gitea/models" |
| 11 | + "code.gitea.io/gitea/modules/git" |
| 12 | + |
| 13 | + "github.com/go-xorm/xorm" |
| 14 | +) |
| 15 | + |
| 16 | +func fixPublisherIDforTagReleases(x *xorm.Engine) error { |
| 17 | + |
| 18 | + type Release struct { |
| 19 | + ID int64 |
| 20 | + RepoID int64 |
| 21 | + Sha1 string |
| 22 | + TagName string |
| 23 | + PublisherID int64 |
| 24 | + } |
| 25 | + |
| 26 | + type Repository struct { |
| 27 | + ID int64 |
| 28 | + OwnerID int64 |
| 29 | + Name string |
| 30 | + } |
| 31 | + |
| 32 | + type User struct { |
| 33 | + ID int64 |
| 34 | + Name string |
| 35 | + Email string |
| 36 | + } |
| 37 | + |
| 38 | + const batchSize = 100 |
| 39 | + sess := x.NewSession() |
| 40 | + defer sess.Close() |
| 41 | + |
| 42 | + if err := sess.Begin(); err != nil { |
| 43 | + return err |
| 44 | + } |
| 45 | + |
| 46 | + var ( |
| 47 | + gitRepoCache = make(map[int64]*git.Repository) |
| 48 | + gitRepo *git.Repository |
| 49 | + repoCache = make(map[int64]*Repository) |
| 50 | + userCache = make(map[int64]*User) |
| 51 | + ok bool |
| 52 | + err error |
| 53 | + ) |
| 54 | + |
| 55 | + for start := 0; ; start += batchSize { |
| 56 | + releases := make([]*Release, 0, batchSize) |
| 57 | + |
| 58 | + if err := sess.Limit(batchSize, start).Asc("id").Where("is_tag=?", true).Find(&releases); err != nil { |
| 59 | + return err |
| 60 | + } |
| 61 | + |
| 62 | + if len(releases) == 0 { |
| 63 | + break |
| 64 | + } |
| 65 | + |
| 66 | + for _, release := range releases { |
| 67 | + gitRepo, ok = gitRepoCache[release.RepoID] |
| 68 | + if !ok { |
| 69 | + repo, ok := repoCache[release.RepoID] |
| 70 | + if !ok { |
| 71 | + repo = new(Repository) |
| 72 | + has, err := sess.ID(release.RepoID).Get(repo) |
| 73 | + if err != nil { |
| 74 | + return err |
| 75 | + } else if !has { |
| 76 | + return fmt.Errorf("Repository %d is not exist", release.RepoID) |
| 77 | + } |
| 78 | + |
| 79 | + repoCache[release.RepoID] = repo |
| 80 | + } |
| 81 | + |
| 82 | + user, ok := userCache[repo.OwnerID] |
| 83 | + if !ok { |
| 84 | + user = new(User) |
| 85 | + has, err := sess.ID(repo.OwnerID).Get(user) |
| 86 | + if err != nil { |
| 87 | + return err |
| 88 | + } else if !has { |
| 89 | + return fmt.Errorf("User %d is not exist", repo.OwnerID) |
| 90 | + } |
| 91 | + |
| 92 | + userCache[repo.OwnerID] = user |
| 93 | + } |
| 94 | + |
| 95 | + gitRepo, err = git.OpenRepository(models.RepoPath(user.Name, repo.Name)) |
| 96 | + if err != nil { |
| 97 | + return err |
| 98 | + } |
| 99 | + gitRepoCache[release.RepoID] = gitRepo |
| 100 | + } |
| 101 | + |
| 102 | + commit, err := gitRepo.GetTagCommit(release.TagName) |
| 103 | + if err != nil { |
| 104 | + return fmt.Errorf("GetTagCommit: %v", err) |
| 105 | + } |
| 106 | + |
| 107 | + u := new(User) |
| 108 | + exists, err := sess.Where("email=?", commit.Author.Email).Get(u) |
| 109 | + if err != nil { |
| 110 | + return err |
| 111 | + } |
| 112 | + |
| 113 | + if !exists { |
| 114 | + continue |
| 115 | + } |
| 116 | + |
| 117 | + release.PublisherID = u.ID |
| 118 | + if _, err := sess.ID(release.ID).Update(release); err != nil { |
| 119 | + return err |
| 120 | + } |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + return sess.Commit() |
| 125 | +} |
0 commit comments