@ -10,7 +10,6 @@ import (
"context"
"context"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"path/filepath"
"strings"
"strings"
"time"
"time"
@ -20,7 +19,6 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
issue_service "code.gitea.io/gitea/services/issue"
issue_service "code.gitea.io/gitea/services/issue"
"github.com/unknwon/com"
"github.com/unknwon/com"
@ -215,18 +213,6 @@ func checkForInvalidation(requests models.PullRequestList, repoID int64, doer *m
return nil
return nil
}
}
func addHeadRepoTasks ( prs [ ] * models . PullRequest ) {
for _ , pr := range prs {
log . Trace ( "addHeadRepoTasks[%d]: composing new test task" , pr . ID )
if err := PushToBaseRepo ( pr ) ; err != nil {
log . Error ( "PushToBaseRepo: %v" , err )
continue
}
AddToTaskQueue ( pr )
}
}
// AddTestPullRequestTask adds new test tasks by given head/base repository and head/base branch,
// AddTestPullRequestTask adds new test tasks by given head/base repository and head/base branch,
// and generate new patch for testing as needed.
// and generate new patch for testing as needed.
func AddTestPullRequestTask ( doer * models . User , repoID int64 , branch string , isSync bool , oldCommitID , newCommitID string ) {
func AddTestPullRequestTask ( doer * models . User , repoID int64 , branch string , isSync bool , oldCommitID , newCommitID string ) {
@ -283,8 +269,14 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy
}
}
}
}
addHeadRepoTasks ( prs )
for _ , pr := range prs {
for _ , pr := range prs {
log . Trace ( "Updating PR[%d]: composing new test task" , pr . ID )
if err := PushToBaseRepo ( pr ) ; err != nil {
log . Error ( "PushToBaseRepo: %v" , err )
continue
}
AddToTaskQueue ( pr )
comment , err := models . CreatePushPullComment ( doer , pr , oldCommitID , newCommitID )
comment , err := models . CreatePushPullComment ( doer , pr , oldCommitID , newCommitID )
if err == nil && comment != nil {
if err == nil && comment != nil {
notification . NotifyPullRequestPushCommits ( doer , pr , comment )
notification . NotifyPullRequestPushCommits ( doer , pr , comment )
@ -389,54 +381,17 @@ func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID st
func PushToBaseRepo ( pr * models . PullRequest ) ( err error ) {
func PushToBaseRepo ( pr * models . PullRequest ) ( err error ) {
log . Trace ( "PushToBaseRepo[%d]: pushing commits to base repo '%s'" , pr . BaseRepoID , pr . GetGitRefName ( ) )
log . Trace ( "PushToBaseRepo[%d]: pushing commits to base repo '%s'" , pr . BaseRepoID , pr . GetGitRefName ( ) )
// Clone base repo.
tmpBasePath , err := models . CreateTemporaryPath ( "pull" )
if err != nil {
log . Error ( "CreateTemporaryPath: %v" , err )
return err
}
defer func ( ) {
err := models . RemoveTemporaryPath ( tmpBasePath )
if err != nil {
log . Error ( "Error whilst removing temporary path: %s Error: %v" , tmpBasePath , err )
}
} ( )
if err := pr . LoadHeadRepo ( ) ; err != nil {
if err := pr . LoadHeadRepo ( ) ; err != nil {
log . Error ( "Unable to load head repository for PR[%d] Error: %v" , pr . ID , err )
log . Error ( "Unable to load head repository for PR[%d] Error: %v" , pr . ID , err )
return err
return err
}
}
headRepoPath := pr . HeadRepo . RepoPath ( )
headRepoPath := pr . HeadRepo . RepoPath ( )
if err := git . Clone ( headRepoPath , tmpBasePath , git . CloneRepoOptions {
Bare : true ,
Shared : true ,
Branch : pr . HeadBranch ,
Quiet : true ,
} ) ; err != nil {
log . Error ( "git clone tmpBasePath: %v" , err )
return err
}
gitRepo , err := git . OpenRepository ( tmpBasePath )
if err != nil {
return fmt . Errorf ( "OpenRepository: %v" , err )
}
defer gitRepo . Close ( )
if err := pr . LoadBaseRepo ( ) ; err != nil {
if err := pr . LoadBaseRepo ( ) ; err != nil {
log . Error ( "Unable to load base repository for PR[%d] Error: %v" , pr . ID , err )
log . Error ( "Unable to load base repository for PR[%d] Error: %v" , pr . ID , err )
return err
return err
}
}
if err := gitRepo . AddRemote ( "base" , pr . BaseRepo . RepoPath ( ) , false ) ; err != nil {
baseRepoPath := pr . BaseRepo . RepoPath ( )
return fmt . Errorf ( "tmpGitRepo.AddRemote: %v" , err )
}
headFile := pr . GetGitRefName ( )
// Remove head in case there is a conflict.
file := filepath . Join ( pr . BaseRepo . RepoPath ( ) , headFile )
_ = util . Remove ( file )
if err = pr . LoadIssue ( ) ; err != nil {
if err = pr . LoadIssue ( ) ; err != nil {
return fmt . Errorf ( "unable to load issue %d for pr %d: %v" , pr . IssueID , pr . ID , err )
return fmt . Errorf ( "unable to load issue %d for pr %d: %v" , pr . IssueID , pr . ID , err )
@ -445,24 +400,26 @@ func PushToBaseRepo(pr *models.PullRequest) (err error) {
return fmt . Errorf ( "unable to load poster %d for pr %d: %v" , pr . Issue . PosterID , pr . ID , err )
return fmt . Errorf ( "unable to load poster %d for pr %d: %v" , pr . Issue . PosterID , pr . ID , err )
}
}
if err = git . Push ( tmpBasePath , git . PushOptions {
gitRefName := pr . GetGitRefName ( )
Remote : "base" ,
Branch : fmt . Sprintf ( "%s:%s" , pr . HeadBranch , headFile ) ,
if err := git . Push ( headRepoPath , git . PushOptions {
Remote : baseRepoPath ,
Branch : pr . HeadBranch + ":" + gitRefName ,
Force : true ,
Force : true ,
// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/...
// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/...
Env : models . InternalPushingEnvironment ( pr . Issue . Poster , pr . BaseRepo ) ,
Env : models . InternalPushingEnvironment ( pr . Issue . Poster , pr . BaseRepo ) ,
} ) ; err != nil {
} ) ; err != nil {
if git . IsErrPushOutOfDate ( err ) {
if git . IsErrPushOutOfDate ( err ) {
// This should not happen as we're using force!
// This should not happen as we're using force!
log . Error ( "Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v" , pr . BaseRepo . FullName ( ) , pr . Index , pr . BaseRepo , headFil e, err )
log . Error ( "Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v" , pr . BaseRepo . FullName ( ) , pr . Index , pr . BaseRepo , gitRefNam e, err )
return err
return err
} else if git . IsErrPushRejected ( err ) {
} else if git . IsErrPushRejected ( err ) {
rejectErr := err . ( * git . ErrPushRejected )
rejectErr := err . ( * git . ErrPushRejected )
log . Info ( "Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v" , pr . BaseRepo . FullName ( ) , pr . Index , pr . BaseRepo , headFil e, rejectErr . StdOut , rejectErr . StdErr , rejectErr . Err )
log . Info ( "Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v" , pr . BaseRepo . FullName ( ) , pr . Index , pr . BaseRepo , gitRefNam e, rejectErr . StdOut , rejectErr . StdErr , rejectErr . Err )
return err
return err
}
}
log . Error ( "Unable to push PR head for %s#%d (%-v:%s) due to Error: %v" , pr . BaseRepo . FullName ( ) , pr . Index , pr . BaseRepo , headFil e, err )
log . Error ( "Unable to push PR head for %s#%d (%-v:%s) due to Error: %v" , pr . BaseRepo . FullName ( ) , pr . Index , pr . BaseRepo , gitRefNam e, err )
return fmt . Errorf ( "Push: %s:%s %s:%s %v" , pr . HeadRepo . FullName ( ) , pr . HeadBranch , pr . BaseRepo . FullName ( ) , headFil e, err )
return fmt . Errorf ( "Push: %s:%s %s:%s %v" , pr . HeadRepo . FullName ( ) , pr . HeadBranch , pr . BaseRepo . FullName ( ) , gitRefNam e, err )
}
}
return nil
return nil