code.gitea.io/gitea@v1.21.7/models/migrations/v1_12/v136.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/graceful"
    15  	"code.gitea.io/gitea/modules/log"
    16  	"code.gitea.io/gitea/modules/setting"
    17  
    18  	"xorm.io/xorm"
    19  )
    20  
    21  func AddCommitDivergenceToPulls(x *xorm.Engine) error {
    22  	type Repository struct {
    23  		ID        int64 `xorm:"pk autoincr"`
    24  		OwnerID   int64 `xorm:"UNIQUE(s) index"`
    25  		OwnerName string
    26  		LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
    27  		Name      string `xorm:"INDEX NOT NULL"`
    28  	}
    29  
    30  	type PullRequest struct {
    31  		ID      int64 `xorm:"pk autoincr"`
    32  		IssueID int64 `xorm:"INDEX"`
    33  		Index   int64
    34  
    35  		CommitsAhead  int
    36  		CommitsBehind int
    37  
    38  		BaseRepoID int64 `xorm:"INDEX"`
    39  		BaseBranch string
    40  
    41  		HasMerged      bool   `xorm:"INDEX"`
    42  		MergedCommitID string `xorm:"VARCHAR(40)"`
    43  	}
    44  
    45  	if err := x.Sync(new(PullRequest)); err != nil {
    46  		return fmt.Errorf("Sync: %w", err)
    47  	}
    48  
    49  	last := 0
    50  	migrated := 0
    51  
    52  	batchSize := setting.Database.IterateBufferSize
    53  	sess := x.NewSession()
    54  	defer sess.Close()
    55  
    56  	ticker := time.NewTicker(5 * time.Second)
    57  	defer ticker.Stop()
    58  	count, err := sess.Where("has_merged = ?", false).Count(new(PullRequest))
    59  	if err != nil {
    60  		return err
    61  	}
    62  	log.Info("%d Unmerged Pull Request(s) to migrate ...", count)
    63  
    64  	for {
    65  		if err := sess.Begin(); err != nil {
    66  			return err
    67  		}
    68  		results := make([]*PullRequest, 0, batchSize)
    69  		err := sess.Where("has_merged = ?", false).OrderBy("id").Limit(batchSize, last).Find(&results)
    70  		if err != nil {
    71  			return err
    72  		}
    73  		if len(results) == 0 {
    74  			break
    75  		}
    76  		last += batchSize
    77  
    78  		for _, pr := range results {
    79  			baseRepo := &Repository{ID: pr.BaseRepoID}
    80  			has, err := x.Table("repository").Get(baseRepo)
    81  			if err != nil {
    82  				return fmt.Errorf("Unable to get base repo %d %w", pr.BaseRepoID, err)
    83  			}
    84  			if !has {
    85  				log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID)
    86  				continue
    87  			}
    88  			userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName))
    89  			repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git")
    90  
    91  			gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
    92  
    93  			divergence, err := git.GetDivergingCommits(graceful.GetManager().HammerContext(), repoPath, pr.BaseBranch, gitRefName)
    94  			if err != nil {
    95  				log.Warn("Could not recalculate Divergence for pull: %d", pr.ID)
    96  				pr.CommitsAhead = 0
    97  				pr.CommitsBehind = 0
    98  			}
    99  			pr.CommitsAhead = divergence.Ahead
   100  			pr.CommitsBehind = divergence.Behind
   101  
   102  			if _, err = sess.ID(pr.ID).Cols("commits_ahead", "commits_behind").Update(pr); err != nil {
   103  				return fmt.Errorf("Update Cols: %w", err)
   104  			}
   105  			migrated++
   106  		}
   107  
   108  		if err := sess.Commit(); err != nil {
   109  			return err
   110  		}
   111  		select {
   112  		case <-ticker.C:
   113  			log.Info(
   114  				"%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...",
   115  				migrated,
   116  				count,
   117  				float64(migrated)/float64(count)*100,
   118  				int(math.Ceil(float64(migrated)/float64(batchSize))),
   119  				count-int64(migrated))
   120  		default:
   121  		}
   122  	}
   123  	log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(migrated)/float64(batchSize))))
   124  	return nil
   125  }