code.gitea.io/gitea@v1.21.7/models/migrations/v1_12/v134.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package v1_12 //nolint 5 6 import ( 7 "fmt" 8 "math" 9 "path/filepath" 10 "strings" 11 "time" 12 13 "code.gitea.io/gitea/modules/git" 14 "code.gitea.io/gitea/modules/log" 15 "code.gitea.io/gitea/modules/setting" 16 17 "xorm.io/xorm" 18 ) 19 20 func RefixMergeBase(x *xorm.Engine) error { 21 type Repository struct { 22 ID int64 `xorm:"pk autoincr"` 23 OwnerID int64 `xorm:"UNIQUE(s) index"` 24 OwnerName string 25 LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"` 26 Name string `xorm:"INDEX NOT NULL"` 27 } 28 29 type PullRequest struct { 30 ID int64 `xorm:"pk autoincr"` 31 Index int64 32 HeadRepoID int64 `xorm:"INDEX"` 33 BaseRepoID int64 `xorm:"INDEX"` 34 HeadBranch string 35 BaseBranch string 36 MergeBase string `xorm:"VARCHAR(40)"` 37 38 HasMerged bool `xorm:"INDEX"` 39 MergedCommitID string `xorm:"VARCHAR(40)"` 40 } 41 42 limit := setting.Database.IterateBufferSize 43 if limit <= 0 { 44 limit = 50 45 } 46 47 ticker := time.NewTicker(5 * time.Second) 48 defer ticker.Stop() 49 count, err := x.Where("has_merged = ?", true).Count(new(PullRequest)) 50 if err != nil { 51 return err 52 } 53 log.Info("%d Merged Pull Request(s) to migrate ...", count) 54 55 i := 0 56 start := 0 57 for { 58 prs := make([]PullRequest, 0, 50) 59 if err := x.Limit(limit, start).Asc("id").Where("has_merged = ?", true).Find(&prs); err != nil { 60 return fmt.Errorf("Find: %w", err) 61 } 62 if len(prs) == 0 { 63 break 64 } 65 66 start += 50 67 for _, pr := range prs { 68 baseRepo := &Repository{ID: pr.BaseRepoID} 69 has, err := x.Table("repository").Get(baseRepo) 70 if err != nil { 71 return fmt.Errorf("Unable to get base repo %d %w", pr.BaseRepoID, err) 72 } 73 if !has { 74 log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID) 75 continue 76 } 77 userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName)) 78 repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git") 79 80 gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index) 81 82 parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath}) 83 if err != nil { 84 log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) 85 continue 86 } 87 parents := strings.Split(strings.TrimSpace(parentsString), " ") 88 if len(parents) < 3 { 89 continue 90 } 91 92 // we should recalculate 93 refs := append([]string{}, parents[1:]...) 94 refs = append(refs, gitRefName) 95 cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...) 96 97 pr.MergeBase, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath}) 98 if err != nil { 99 log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) 100 continue 101 } 102 pr.MergeBase = strings.TrimSpace(pr.MergeBase) 103 x.ID(pr.ID).Cols("merge_base").Update(pr) 104 i++ 105 select { 106 case <-ticker.C: 107 log.Info("%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...", i, count, float64(i)/float64(count)*100, int(math.Ceil(float64(i)/float64(limit))), count-int64(i)) 108 default: 109 } 110 } 111 } 112 113 log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(i)/float64(limit)))) 114 return nil 115 }