code.gitea.io/gitea@v1.21.7/models/migrations/v1_9/v82.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package v1_9 //nolint 5 6 import ( 7 "fmt" 8 "path/filepath" 9 "strings" 10 11 "code.gitea.io/gitea/modules/git" 12 "code.gitea.io/gitea/modules/setting" 13 14 "xorm.io/xorm" 15 ) 16 17 func FixReleaseSha1OnReleaseTable(x *xorm.Engine) error { 18 type Release struct { 19 ID int64 20 RepoID int64 21 Sha1 string 22 TagName string 23 } 24 25 type Repository struct { 26 ID int64 27 OwnerID int64 28 Name string 29 } 30 31 type User struct { 32 ID int64 33 Name string 34 } 35 36 // UserPath returns the path absolute path of user repositories. 37 UserPath := func(userName string) string { 38 return filepath.Join(setting.RepoRootPath, strings.ToLower(userName)) 39 } 40 41 // RepoPath returns repository path by given user and repository name. 42 RepoPath := func(userName, repoName string) string { 43 return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".git") 44 } 45 46 // Update release sha1 47 const batchSize = 100 48 sess := x.NewSession() 49 defer sess.Close() 50 51 var ( 52 err error 53 count int 54 gitRepoCache = make(map[int64]*git.Repository) 55 repoCache = make(map[int64]*Repository) 56 userCache = make(map[int64]*User) 57 ) 58 59 if err = sess.Begin(); err != nil { 60 return err 61 } 62 63 for start := 0; ; start += batchSize { 64 releases := make([]*Release, 0, batchSize) 65 if err = sess.Limit(batchSize, start).Asc("id").Where("is_tag=?", false).Find(&releases); err != nil { 66 return err 67 } 68 if len(releases) == 0 { 69 break 70 } 71 72 for _, release := range releases { 73 gitRepo, ok := gitRepoCache[release.RepoID] 74 if !ok { 75 repo, ok := repoCache[release.RepoID] 76 if !ok { 77 repo = new(Repository) 78 has, err := sess.ID(release.RepoID).Get(repo) 79 if err != nil { 80 return err 81 } else if !has { 82 return fmt.Errorf("Repository %d is not exist", release.RepoID) 83 } 84 85 repoCache[release.RepoID] = repo 86 } 87 88 user, ok := userCache[repo.OwnerID] 89 if !ok { 90 user = new(User) 91 has, err := sess.ID(repo.OwnerID).Get(user) 92 if err != nil { 93 return err 94 } else if !has { 95 return fmt.Errorf("User %d is not exist", repo.OwnerID) 96 } 97 98 userCache[repo.OwnerID] = user 99 } 100 101 gitRepo, err = git.OpenRepository(git.DefaultContext, RepoPath(user.Name, repo.Name)) 102 if err != nil { 103 return err 104 } 105 defer gitRepo.Close() 106 gitRepoCache[release.RepoID] = gitRepo 107 } 108 109 release.Sha1, err = gitRepo.GetTagCommitID(release.TagName) 110 if err != nil && !git.IsErrNotExist(err) { 111 return err 112 } 113 114 if err == nil { 115 if _, err = sess.ID(release.ID).Cols("sha1").Update(release); err != nil { 116 return err 117 } 118 } 119 120 count++ 121 if count >= 1000 { 122 if err = sess.Commit(); err != nil { 123 return err 124 } 125 if err = sess.Begin(); err != nil { 126 return err 127 } 128 count = 0 129 } 130 } 131 } 132 return sess.Commit() 133 }