code.gitea.io/gitea@v1.21.7/models/migrations/v1_12/v128.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 FixMergeBase(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 50 count, err := x.Count(new(PullRequest)) 51 if err != nil { 52 return err 53 } 54 log.Info("%d Pull Request(s) to migrate ...", count) 55 56 i := 0 57 start := 0 58 for { 59 prs := make([]PullRequest, 0, 50) 60 if err := x.Limit(limit, start).Asc("id").Find(&prs); err != nil { 61 return fmt.Errorf("Find: %w", err) 62 } 63 if len(prs) == 0 { 64 break 65 } 66 67 start += 50 68 for _, pr := range prs { 69 baseRepo := &Repository{ID: pr.BaseRepoID} 70 has, err := x.Table("repository").Get(baseRepo) 71 if err != nil { 72 return fmt.Errorf("Unable to get base repo %d %w", pr.BaseRepoID, err) 73 } 74 if !has { 75 log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID) 76 continue 77 } 78 userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName)) 79 repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git") 80 81 gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index) 82 83 if !pr.HasMerged { 84 var err error 85 pr.MergeBase, _, err = git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(&git.RunOpts{Dir: repoPath}) 86 if err != nil { 87 var err2 error 88 pr.MergeBase, _, err2 = git.NewCommand(git.DefaultContext, "rev-parse").AddDynamicArguments(git.BranchPrefix + pr.BaseBranch).RunStdString(&git.RunOpts{Dir: repoPath}) 89 if err2 != nil { 90 log.Error("Unable to get merge base for PR ID %d, Index %d in %s/%s. Error: %v & %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err, err2) 91 continue 92 } 93 } 94 } else { 95 parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath}) 96 if err != nil { 97 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) 98 continue 99 } 100 parents := strings.Split(strings.TrimSpace(parentsString), " ") 101 if len(parents) < 2 { 102 continue 103 } 104 105 refs := append([]string{}, parents[1:]...) 106 refs = append(refs, gitRefName) 107 cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...) 108 109 pr.MergeBase, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath}) 110 if err != nil { 111 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) 112 continue 113 } 114 } 115 pr.MergeBase = strings.TrimSpace(pr.MergeBase) 116 x.ID(pr.ID).Cols("merge_base").Update(pr) 117 i++ 118 select { 119 case <-ticker.C: 120 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)) 121 default: 122 } 123 } 124 } 125 log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(i)/float64(limit)))) 126 return nil 127 }