@@ -6,6 +6,8 @@ package pull
66
77import (
88 "fmt"
9+ "os"
10+ "path"
911
1012 "code.gitea.io/gitea/models"
1113 "code.gitea.io/gitea/modules/git"
@@ -33,6 +35,10 @@ func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int6
3335 pr .Issue = pull
3436 pull .PullRequest = pr
3537
38+ if err := PushToBaseRepo (pr ); err != nil {
39+ return err
40+ }
41+
3642 notification .NotifyNewPullRequest (pr )
3743
3844 return nil
@@ -60,7 +66,7 @@ func checkForInvalidation(requests models.PullRequestList, repoID int64, doer *m
6066func addHeadRepoTasks (prs []* models.PullRequest ) {
6167 for _ , pr := range prs {
6268 log .Trace ("addHeadRepoTasks[%d]: composing new test task" , pr .ID )
63- if err := pr . PushToBaseRepo (); err != nil {
69+ if err := PushToBaseRepo (pr ); err != nil {
6470 log .Error ("PushToBaseRepo: %v" , err )
6571 continue
6672 }
@@ -107,3 +113,45 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy
107113 AddToTaskQueue (pr )
108114 }
109115}
116+
117+ // PushToBaseRepo pushes commits from branches of head repository to
118+ // corresponding branches of base repository.
119+ // FIXME: Only push branches that are actually updates?
120+ func PushToBaseRepo (pr * models.PullRequest ) (err error ) {
121+ log .Trace ("PushToBaseRepo[%d]: pushing commits to base repo '%s'" , pr .BaseRepoID , pr .GetGitRefName ())
122+
123+ headRepoPath := pr .HeadRepo .RepoPath ()
124+ headGitRepo , err := git .OpenRepository (headRepoPath )
125+ if err != nil {
126+ return fmt .Errorf ("OpenRepository: %v" , err )
127+ }
128+ defer headGitRepo .Close ()
129+
130+ tmpRemoteName := fmt .Sprintf ("tmp-pull-%d" , pr .ID )
131+ if err = headGitRepo .AddRemote (tmpRemoteName , pr .BaseRepo .RepoPath (), false ); err != nil {
132+ return fmt .Errorf ("headGitRepo.AddRemote: %v" , err )
133+ }
134+ // Make sure to remove the remote even if the push fails
135+ defer func () {
136+ if err := headGitRepo .RemoveRemote (tmpRemoteName ); err != nil {
137+ log .Error ("PushToBaseRepo: RemoveRemote: %s" , err )
138+ }
139+ }()
140+
141+ headFile := pr .GetGitRefName ()
142+
143+ // Remove head in case there is a conflict.
144+ file := path .Join (pr .BaseRepo .RepoPath (), headFile )
145+
146+ _ = os .Remove (file )
147+
148+ if err = git .Push (headRepoPath , git.PushOptions {
149+ Remote : tmpRemoteName ,
150+ Branch : fmt .Sprintf ("%s:%s" , pr .HeadBranch , headFile ),
151+ Force : true ,
152+ }); err != nil {
153+ return fmt .Errorf ("Push: %v" , err )
154+ }
155+
156+ return nil
157+ }
0 commit comments