2020-03-31 16:42:44 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2020-03-31 16:42:44 +03:00
2022-11-02 11:54:36 +03:00
package v1_12 //nolint
2020-03-31 16:42:44 +03:00
import (
"fmt"
2020-05-30 01:18:24 +03:00
"math"
2020-03-31 16:42:44 +03:00
"path/filepath"
"strings"
2020-05-30 01:18:24 +03:00
"time"
2020-03-31 16:42:44 +03:00
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"xorm.io/xorm"
)
2022-11-02 11:54:36 +03:00
func RefixMergeBase ( x * xorm . Engine ) error {
2020-03-31 16:42:44 +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 {
ID int64 ` xorm:"pk autoincr" `
Index int64
HeadRepoID int64 ` xorm:"INDEX" `
BaseRepoID int64 ` xorm:"INDEX" `
HeadBranch string
BaseBranch string
MergeBase string ` xorm:"VARCHAR(40)" `
HasMerged bool ` xorm:"INDEX" `
MergedCommitID string ` xorm:"VARCHAR(40)" `
}
2021-03-14 21:52:12 +03:00
limit := setting . Database . IterateBufferSize
2020-03-31 16:42:44 +03:00
if limit <= 0 {
limit = 50
}
2020-05-30 01:18:24 +03:00
ticker := time . NewTicker ( 5 * time . Second )
defer ticker . Stop ( )
count , err := x . Where ( "has_merged = ?" , true ) . Count ( new ( PullRequest ) )
if err != nil {
return err
}
log . Info ( "%d Merged Pull Request(s) to migrate ..." , count )
2020-03-31 16:42:44 +03:00
i := 0
2020-05-30 01:18:24 +03:00
start := 0
2020-03-31 16:42:44 +03:00
for {
prs := make ( [ ] PullRequest , 0 , 50 )
2020-05-30 01:18:24 +03:00
if err := x . Limit ( limit , start ) . Asc ( "id" ) . Where ( "has_merged = ?" , true ) . Find ( & prs ) ; err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "Find: %w" , err )
2020-03-31 16:42:44 +03:00
}
if len ( prs ) == 0 {
break
}
2020-05-30 01:18:24 +03:00
start += 50
2020-03-31 16:42:44 +03:00
for _ , pr := range prs {
baseRepo := & Repository { ID : pr . BaseRepoID }
has , err := x . Table ( "repository" ) . Get ( baseRepo )
if err != nil {
2022-10-24 22:29:17 +03:00
return fmt . Errorf ( "Unable to get base repo %d %w" , pr . BaseRepoID , err )
2020-03-31 16:42:44 +03:00
}
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 )
2022-10-23 17:44:45 +03:00
parentsString , _ , err := git . NewCommand ( git . DefaultContext , "rev-list" , "--parents" , "-n" , "1" ) . AddDynamicArguments ( pr . MergedCommitID ) . RunStdString ( & git . RunOpts { Dir : repoPath } )
2020-03-31 16:42:44 +03:00
if err != nil {
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 )
continue
}
parents := strings . Split ( strings . TrimSpace ( parentsString ) , " " )
if len ( parents ) < 3 {
continue
}
// we should recalculate
2022-10-23 17:44:45 +03:00
refs := append ( [ ] string { } , parents [ 1 : ] ... )
refs = append ( refs , gitRefName )
cmd := git . NewCommand ( git . DefaultContext , "merge-base" ) . AddDashesAndList ( refs ... )
2020-03-31 16:42:44 +03:00
2022-10-23 17:44:45 +03:00
pr . MergeBase , _ , err = cmd . RunStdString ( & git . RunOpts { Dir : repoPath } )
2020-03-31 16:42:44 +03:00
if err != nil {
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 )
continue
}
pr . MergeBase = strings . TrimSpace ( pr . MergeBase )
x . ID ( pr . ID ) . Cols ( "merge_base" ) . Update ( pr )
2020-05-30 01:18:24 +03:00
i ++
select {
case <- ticker . C :
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 ) )
default :
}
2020-03-31 16:42:44 +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 ( i ) / float64 ( limit ) ) ) )
2020-03-31 16:42:44 +03:00
return nil
}