@@ -43,6 +43,7 @@ func getPullWorkingLockKey(prID int64) string {
4343type  NewPullRequestOptions  struct  {
4444	Repo             * repo_model.Repository 
4545	Issue            * issues_model.Issue 
46+ 	HeadCommitID     string 
4647	LabelIDs         []int64 
4748	AttachmentUUIDs  []string 
4849	PullRequest      * issues_model.PullRequest 
@@ -53,6 +54,10 @@ type NewPullRequestOptions struct {
5354
5455// NewPullRequest creates new pull request with labels for repository. 
5556func  NewPullRequest (ctx  context.Context , opts  * NewPullRequestOptions ) error  {
57+ 	if  opts .PullRequest .Flow  ==  issues_model .PullRequestFlowAGit  &&  opts .HeadCommitID  ==  ""  {
58+ 		return  errors .New ("head commit ID cannot be empty for agit flow" )
59+ 	}
60+ 
5661	repo , issue , labelIDs , uuids , pr , assigneeIDs  :=  opts .Repo , opts .Issue , opts .LabelIDs , opts .AttachmentUUIDs , opts .PullRequest , opts .AssigneeIDs 
5762	if  err  :=  issue .LoadPoster (ctx ); err  !=  nil  {
5863		return  err 
@@ -98,13 +103,6 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error {
98103		return  err 
99104	}
100105
101- 	divergence , err  :=  git .GetDivergingCommits (ctx , prCtx .tmpBasePath , baseBranch , trackingBranch )
102- 	if  err  !=  nil  {
103- 		return  err 
104- 	}
105- 	pr .CommitsAhead  =  divergence .Ahead 
106- 	pr .CommitsBehind  =  divergence .Behind 
107- 
108106	assigneeCommentMap  :=  make (map [int64 ]* issues_model.Comment )
109107
110108	// add first push codes comment 
@@ -131,15 +129,27 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error {
131129		pr .Issue  =  issue 
132130		issue .PullRequest  =  pr 
133131
134- 		if  pr .Flow  ==  issues_model .PullRequestFlowGithub  {
135- 			err  =  PushToBaseRepo (ctx , pr )
132+ 		// update head commit id into git repository 
133+ 		if  pr .Flow  ==  issues_model .PullRequestFlowAGit  {
134+ 			err  =  UpdatePullRequestAgitFlowHead (ctx , pr , opts .HeadCommitID )
136135		} else  {
137- 			err  =  UpdateRef (ctx , pr )
136+ 			err  =  UpdatePullRequestGithubFlowHead (ctx , pr )
138137		}
139138		if  err  !=  nil  {
140139			return  err 
141140		}
142141
142+ 		// update commits ahead and behind 
143+ 		divergence , err  :=  git .GetDivergingCommits (ctx , pr .BaseRepo .RepoPath (), pr .BaseBranch , pr .GetGitHeadRefName ())
144+ 		if  err  !=  nil  {
145+ 			return  err 
146+ 		}
147+ 		pr .CommitsAhead  =  divergence .Ahead 
148+ 		pr .CommitsBehind  =  divergence .Behind 
149+ 		if  _ , err  :=  db .GetEngine (ctx ).ID (pr .ID ).Cols ("commits_ahead" , "commits_behind" ).NoAutoTime ().Update (pr ); err  !=  nil  {
150+ 			return  err 
151+ 		}
152+ 
143153		if  _ , err  :=  CreatePushPullComment (ctx , issue .Poster , pr , git .BranchPrefix + pr .BaseBranch , pr .GetGitHeadRefName (), false ); err  !=  nil  {
144154			return  err 
145155		}
@@ -388,7 +398,7 @@ func AddTestPullRequestTask(opts TestPullRequestOptions) {
388398		for  _ , pr  :=  range  prs  {
389399			log .Trace ("Updating PR[%d]: composing new test task" , pr .ID )
390400			if  pr .Flow  ==  issues_model .PullRequestFlowGithub  {
391- 				if  err  :=  PushToBaseRepo (ctx , pr ); err  !=  nil  {
401+ 				if  err  :=  UpdatePullRequestGithubFlowHead (ctx , pr ); err  !=  nil  {
392402					log .Error ("PushToBaseRepo: %v" , err )
393403					continue 
394404				}
@@ -546,68 +556,6 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest,
546556	return  false , nil 
547557}
548558
549- // PushToBaseRepo pushes commits from branches of head repository to 
550- // corresponding branches of base repository. 
551- // FIXME: Only push branches that are actually updates? 
552- func  PushToBaseRepo (ctx  context.Context , pr  * issues_model.PullRequest ) (err  error ) {
553- 	return  pushToBaseRepoHelper (ctx , pr , "" )
554- }
555- 
556- func  pushToBaseRepoHelper (ctx  context.Context , pr  * issues_model.PullRequest , prefixHeadBranch  string ) (err  error ) {
557- 	log .Trace ("PushToBaseRepo[%d]: pushing commits to base repo '%s'" , pr .BaseRepoID , pr .GetGitHeadRefName ())
558- 
559- 	if  err  :=  pr .LoadHeadRepo (ctx ); err  !=  nil  {
560- 		log .Error ("Unable to load head repository for PR[%d] Error: %v" , pr .ID , err )
561- 		return  err 
562- 	}
563- 	headRepoPath  :=  pr .HeadRepo .RepoPath ()
564- 
565- 	if  err  :=  pr .LoadBaseRepo (ctx ); err  !=  nil  {
566- 		log .Error ("Unable to load base repository for PR[%d] Error: %v" , pr .ID , err )
567- 		return  err 
568- 	}
569- 	baseRepoPath  :=  pr .BaseRepo .RepoPath ()
570- 
571- 	if  err  =  pr .LoadIssue (ctx ); err  !=  nil  {
572- 		return  fmt .Errorf ("unable to load issue %d for pr %d: %w" , pr .IssueID , pr .ID , err )
573- 	}
574- 	if  err  =  pr .Issue .LoadPoster (ctx ); err  !=  nil  {
575- 		return  fmt .Errorf ("unable to load poster %d for pr %d: %w" , pr .Issue .PosterID , pr .ID , err )
576- 	}
577- 
578- 	gitRefName  :=  pr .GetGitHeadRefName ()
579- 
580- 	if  err  :=  git .Push (ctx , headRepoPath , git.PushOptions {
581- 		Remote : baseRepoPath ,
582- 		Branch : prefixHeadBranch  +  pr .HeadBranch  +  ":"  +  gitRefName ,
583- 		Force :  true ,
584- 		// Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/... 
585- 		Env : repo_module .InternalPushingEnvironment (pr .Issue .Poster , pr .BaseRepo ),
586- 	}); err  !=  nil  {
587- 		if  git .IsErrPushOutOfDate (err ) {
588- 			// This should not happen as we're using force! 
589- 			log .Error ("Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v" , pr .BaseRepo .FullName (), pr .Index , pr .BaseRepo , gitRefName , err )
590- 			return  err 
591- 		} else  if  git .IsErrPushRejected (err ) {
592- 			rejectErr  :=  err .(* git.ErrPushRejected )
593- 			log .Info ("Unable to push PR head for %s#%d (%-v:%s) due to rejection:\n Stdout: %s\n Stderr: %s\n Error: %v" , pr .BaseRepo .FullName (), pr .Index , pr .BaseRepo , gitRefName , rejectErr .StdOut , rejectErr .StdErr , rejectErr .Err )
594- 			return  err 
595- 		} else  if  git .IsErrMoreThanOne (err ) {
596- 			if  prefixHeadBranch  !=  ""  {
597- 				log .Info ("Can't push with %s%s" , prefixHeadBranch , pr .HeadBranch )
598- 				return  err 
599- 			}
600- 			log .Info ("Retrying to push with %s%s" , git .BranchPrefix , pr .HeadBranch )
601- 			err  =  pushToBaseRepoHelper (ctx , pr , git .BranchPrefix )
602- 			return  err 
603- 		}
604- 		log .Error ("Unable to push PR head for %s#%d (%-v:%s) due to Error: %v" , pr .BaseRepo .FullName (), pr .Index , pr .BaseRepo , gitRefName , err )
605- 		return  fmt .Errorf ("Push: %s:%s %s:%s %w" , pr .HeadRepo .FullName (), pr .HeadBranch , pr .BaseRepo .FullName (), gitRefName , err )
606- 	}
607- 
608- 	return  nil 
609- }
610- 
611559// UpdatePullsRefs update all the PRs head file pointers like /refs/pull/1/head so that it will be dependent by other operations 
612560func  UpdatePullsRefs (ctx  context.Context , repo  * repo_model.Repository , update  * repo_module.PushUpdateOptions ) {
613561	branch  :=  update .RefFullName .BranchName ()
@@ -619,27 +567,43 @@ func UpdatePullsRefs(ctx context.Context, repo *repo_model.Repository, update *r
619567		for  _ , pr  :=  range  prs  {
620568			log .Trace ("Updating PR[%d]: composing new test task" , pr .ID )
621569			if  pr .Flow  ==  issues_model .PullRequestFlowGithub  {
622- 				if  err  :=  PushToBaseRepo (ctx , pr ); err  !=  nil  {
623- 					log .Error ("PushToBaseRepo : %v" , err )
570+ 				if  err  :=  UpdatePullRequestGithubFlowHead (ctx , pr ); err  !=  nil  {
571+ 					log .Error ("UpdatePullRequestHead : %v" , err )
624572				}
625573			}
626574		}
627575	}
628576}
629577
630- // UpdateRef update refs/pull/id/head directly for agit flow pull request 
631- func  UpdateRef (ctx  context.Context , pr  * issues_model.PullRequest ) (err  error ) {
632- 	log .Trace ("UpdateRef[%d]: upgate pull request ref in base repo '%s'" , pr .ID , pr .GetGitHeadRefName ())
578+ func  UpdatePullRequestAgitFlowHead (ctx  context.Context , pr  * issues_model.PullRequest , commitID  string ) error  {
579+ 	log .Trace ("UpdateAgitPullRequestHead[%d]: update pull request head in base repo '%s'" , pr .ID , pr .GetGitHeadRefName ())
580+ 
581+ 	_ , _ , err  :=  git .NewCommand ("update-ref" ).AddDynamicArguments (pr .GetGitHeadRefName (), commitID ).RunStdString (ctx , & git.RunOpts {Dir : pr .BaseRepo .RepoPath ()})
582+ 	return  err 
583+ }
584+ 
585+ // UpdatePullRequestHeadRef updates the head reference of a pull request 
586+ func  UpdatePullRequestGithubFlowHead (ctx  context.Context , pr  * issues_model.PullRequest ) error  {
587+ 	log .Trace ("UpdatePullRequestHeadRef[%d]: update pull request ref in base repo '%s'" , pr .ID , pr .GetGitHeadRefName ())
588+ 
633589	if  err  :=  pr .LoadBaseRepo (ctx ); err  !=  nil  {
634- 		log .Error ("Unable to load base repository for PR[%d] Error: %v" , pr .ID , err )
635590		return  err 
636591	}
637592
638- 	_ , _ , err  =  git .NewCommand ("update-ref" ).AddDynamicArguments (pr .GetGitHeadRefName (), pr .HeadCommitID ).RunStdString (ctx , & git.RunOpts {Dir : pr .BaseRepo .RepoPath ()})
639- 	if  err  !=  nil  {
640- 		log .Error ("Unable to update ref in base repository for PR[%d] Error: %v" , pr .ID , err )
593+ 	if  pr .IsSameRepo () { // for agit flow or github flow in the same repository 
594+ 		_ , _ , err  :=  git .NewCommand ("update-ref" ).AddDynamicArguments (pr .GetGitHeadRefName (), pr .HeadBranch ).RunStdString (ctx , & git.RunOpts {Dir : pr .BaseRepo .RepoPath ()})
595+ 		return  err 
596+ 	}
597+ 
598+ 	// for cross repository pull request 
599+ 	if  err  :=  pr .LoadHeadRepo (ctx ); err  !=  nil  {
600+ 		return  err 
641601	}
642602
603+ 	_ , _ , err  :=  git .NewCommand ("fetch" , "--no-tags" , "--refmap=" ).
604+ 		AddDynamicArguments (pr .HeadRepo .RepoPath ()).
605+ 		AddDynamicArguments (fmt .Sprintf ("refs/heads/%s:%s" , pr .HeadBranch , pr .GetGitHeadRefName ())).
606+ 		RunStdString (ctx , & git.RunOpts {Dir : pr .BaseRepo .RepoPath ()})
643607	return  err 
644608}
645609
@@ -803,12 +767,12 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
803767	if  pr .Flow  ==  issues_model .PullRequestFlowGithub  {
804768		headCommit , err  =  gitRepo .GetBranchCommit (pr .HeadBranch )
805769	} else  {
806- 		pr . HeadCommitID , err  =  gitRepo .GetRefCommitID (pr .GetGitHeadRefName ())
770+ 		headCommitID , err  : =gitRepo .GetRefCommitID (pr .GetGitHeadRefName ())
807771		if  err  !=  nil  {
808772			log .Error ("Unable to get head commit: %s Error: %v" , pr .GetGitHeadRefName (), err )
809773			return  "" 
810774		}
811- 		headCommit , err  =  gitRepo .GetCommit (pr . HeadCommitID )
775+ 		headCommit , err  =  gitRepo .GetCommit (headCommitID )
812776	}
813777	if  err  !=  nil  {
814778		log .Error ("Unable to get head commit: %s Error: %v" , pr .HeadBranch , err )
@@ -1030,11 +994,11 @@ func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, br
1030994			return  false , err 
1031995		}
1032996	} else  {
1033- 		pr . HeadCommitID , err  =  baseGitRepo .GetRefCommitID (pr .GetGitHeadRefName ())
997+ 		headCommitID , err  : =baseGitRepo .GetRefCommitID (pr .GetGitHeadRefName ())
1034998		if  err  !=  nil  {
1035999			return  false , err 
10361000		}
1037- 		if  headCommit , err  =  baseGitRepo .GetCommit (pr . HeadCommitID ); err  !=  nil  {
1001+ 		if  headCommit , err  =  baseGitRepo .GetCommit (headCommitID ); err  !=  nil  {
10381002			return  false , err 
10391003		}
10401004	}
0 commit comments