2020-04-14 16:53:34 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"fmt"
2020-05-30 01:18:24 +03:00
"math"
"path/filepath"
"strings"
"time"
2020-04-14 16:53:34 +03:00
2020-05-30 01:18:24 +03:00
"code.gitea.io/gitea/modules/git"
2020-04-14 16:53:34 +03:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"xorm.io/xorm"
)
func addCommitDivergenceToPulls ( x * xorm . Engine ) error {
2020-05-30 01:18:24 +03:00
type Repository struct {
ID int64 ` xorm:"pk autoincr" `
OwnerID int64 ` xorm:"UNIQUE(s) index" `
OwnerName string
LowerName string ` xorm:"UNIQUE(s) INDEX NOT NULL" `
Name string ` xorm:"INDEX NOT NULL" `
}
type PullRequest struct {
2020-07-22 17:27:22 +03:00
ID int64 ` xorm:"pk autoincr" `
IssueID int64 ` xorm:"INDEX" `
Index int64
2020-05-30 01:18:24 +03:00
CommitsAhead int
CommitsBehind int
BaseRepoID int64 ` xorm:"INDEX" `
BaseBranch string
HasMerged bool ` xorm:"INDEX" `
MergedCommitID string ` xorm:"VARCHAR(40)" `
}
2020-04-14 16:53:34 +03:00
2020-07-22 17:27:22 +03:00
if err := x . Sync2 ( new ( PullRequest ) ) ; err != nil {
2020-04-14 16:53:34 +03:00
return fmt . Errorf ( "Sync2: %v" , err )
}
2020-05-30 01:18:24 +03:00
last := 0
migrated := 0
2020-04-14 16:53:34 +03:00
batchSize := setting . Database . IterateBufferSize
sess := x . NewSession ( )
defer sess . Close ( )
2020-05-30 01:18:24 +03:00
ticker := time . NewTicker ( 5 * time . Second )
defer ticker . Stop ( )
count , err := sess . Where ( "has_merged = ?" , false ) . Count ( new ( PullRequest ) )
if err != nil {
return err
}
log . Info ( "%d Unmerged Pull Request(s) to migrate ..." , count )
2020-04-14 16:53:34 +03:00
for {
if err := sess . Begin ( ) ; err != nil {
return err
}
2021-03-14 21:52:12 +03:00
results := make ( [ ] * PullRequest , 0 , batchSize )
2020-04-14 16:53:34 +03:00
err := sess . Where ( "has_merged = ?" , false ) . OrderBy ( "id" ) . Limit ( batchSize , last ) . Find ( & results )
if err != nil {
return err
}
if len ( results ) == 0 {
break
}
2020-05-30 01:18:24 +03:00
last += batchSize
2020-04-14 16:53:34 +03:00
for _ , pr := range results {
2020-05-30 01:18:24 +03:00
baseRepo := & Repository { ID : pr . BaseRepoID }
has , err := x . Table ( "repository" ) . Get ( baseRepo )
if err != nil {
return fmt . Errorf ( "Unable to get base repo %d %v" , pr . BaseRepoID , err )
}
if ! has {
log . Error ( "Missing base repo with id %d for PR ID %d" , pr . BaseRepoID , pr . ID )
continue
}
userPath := filepath . Join ( setting . RepoRootPath , strings . ToLower ( baseRepo . OwnerName ) )
repoPath := filepath . Join ( userPath , strings . ToLower ( baseRepo . Name ) + ".git" )
gitRefName := fmt . Sprintf ( "refs/pull/%d/head" , pr . Index )
divergence , err := git . GetDivergingCommits ( repoPath , pr . BaseBranch , gitRefName )
2020-04-14 16:53:34 +03:00
if err != nil {
log . Warn ( "Could not recalculate Divergence for pull: %d" , pr . ID )
pr . CommitsAhead = 0
pr . CommitsBehind = 0
}
2020-05-30 01:18:24 +03:00
pr . CommitsAhead = divergence . Ahead
pr . CommitsBehind = divergence . Behind
2020-04-14 16:53:34 +03:00
if _ , err = sess . ID ( pr . ID ) . Cols ( "commits_ahead" , "commits_behind" ) . Update ( pr ) ; err != nil {
return fmt . Errorf ( "Update Cols: %v" , err )
}
2020-05-30 01:18:24 +03:00
migrated ++
2020-04-14 16:53:34 +03:00
}
if err := sess . Commit ( ) ; err != nil {
return err
}
2020-05-30 01:18:24 +03:00
select {
case <- ticker . C :
log . Info (
"%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ..." ,
migrated ,
count ,
float64 ( migrated ) / float64 ( count ) * 100 ,
int ( math . Ceil ( float64 ( migrated ) / float64 ( batchSize ) ) ) ,
count - int64 ( migrated ) )
default :
}
2020-04-14 16:53:34 +03:00
}
2020-05-30 01:18:24 +03:00
log . Info ( "Completed migrating %d Pull Request(s) in: %d batches" , count , int ( math . Ceil ( float64 ( migrated ) / float64 ( batchSize ) ) ) )
2020-04-14 16:53:34 +03:00
return nil
}