@@ -12,17 +12,19 @@ import (
1212 repo_model "code.gitea.io/gitea/models/repo"
1313 user_model "code.gitea.io/gitea/models/user"
1414 "code.gitea.io/gitea/modules/git"
15+ "code.gitea.io/gitea/modules/gitrepo"
1516 repo_module "code.gitea.io/gitea/modules/repository"
1617 "code.gitea.io/gitea/modules/util"
1718 "code.gitea.io/gitea/services/pull"
1819)
1920
2021type UpstreamDivergingInfo struct {
21- BaseIsNewer bool
22- CommitsBehind int
23- CommitsAhead int
22+ BaseHasNewCommits bool
23+ CommitsBehind int
24+ CommitsAhead int
2425}
2526
27+ // MergeUpstream merges the base repository's default branch into the fork repository's current branch.
2628func MergeUpstream (ctx context.Context , doer * user_model.User , repo * repo_model.Repository , branch string ) (mergeStyle string , err error ) {
2729 if err = repo .MustNotBeArchived (); err != nil {
2830 return "" , err
@@ -32,7 +34,7 @@ func MergeUpstream(ctx context.Context, doer *user_model.User, repo *repo_model.
3234 }
3335 err = git .Push (ctx , repo .BaseRepo .RepoPath (), git.PushOptions {
3436 Remote : repo .RepoPath (),
35- Branch : fmt .Sprintf ("%s:%s" , branch , branch ),
37+ Branch : fmt .Sprintf ("%s:%s" , repo . BaseRepo . DefaultBranch , branch ),
3638 Env : repo_module .PushingEnvironment (doer , repo ),
3739 })
3840 if err == nil {
@@ -64,7 +66,7 @@ func MergeUpstream(ctx context.Context, doer *user_model.User, repo *repo_model.
6466 BaseRepoID : repo .BaseRepo .ID ,
6567 BaseRepo : repo .BaseRepo ,
6668 HeadBranch : branch , // maybe HeadCommitID is not needed
67- BaseBranch : branch ,
69+ BaseBranch : repo . BaseRepo . DefaultBranch ,
6870 }
6971 fakeIssue .PullRequest = fakePR
7072 err = pull .Update (ctx , fakePR , doer , "merge upstream" , false )
@@ -74,6 +76,7 @@ func MergeUpstream(ctx context.Context, doer *user_model.User, repo *repo_model.
7476 return "merge" , nil
7577}
7678
79+ // GetUpstreamDivergingInfo returns the information about the divergence between the fork repository's branch and the base repository's default branch.
7780func GetUpstreamDivergingInfo (ctx context.Context , repo * repo_model.Repository , branch string ) (* UpstreamDivergingInfo , error ) {
7881 if ! repo .IsFork {
7982 return nil , util .NewInvalidArgumentErrorf ("repo is not a fork" )
@@ -92,7 +95,7 @@ func GetUpstreamDivergingInfo(ctx context.Context, repo *repo_model.Repository,
9295 return nil , err
9396 }
9497
95- baseBranch , err := git_model .GetBranch (ctx , repo .BaseRepo .ID , branch )
98+ baseBranch , err := git_model .GetBranch (ctx , repo .BaseRepo .ID , repo . BaseRepo . DefaultBranch )
9699 if err != nil {
97100 return nil , err
98101 }
@@ -102,14 +105,42 @@ func GetUpstreamDivergingInfo(ctx context.Context, repo *repo_model.Repository,
102105 return info , nil
103106 }
104107
105- // TODO: if the fork repo has new commits, this call will fail:
108+ // if the fork repo has new commits, this call will fail because they are not in the base repo
106109 // exit status 128 - fatal: Invalid symmetric difference expression aaaaaaaaaaaa...bbbbbbbbbbbb
107- // so at the moment, we are not able to handle this case, should be improved in the future
110+ // so at the moment, we first check the update time, then check whether the fork branch has base's head
108111 diff , err := git .GetDivergingCommits (ctx , repo .BaseRepo .RepoPath (), baseBranch .CommitID , forkBranch .CommitID )
109112 if err != nil {
110- info .BaseIsNewer = baseBranch .UpdatedUnix > forkBranch .UpdatedUnix
113+ info .BaseHasNewCommits = baseBranch .UpdatedUnix > forkBranch .UpdatedUnix
114+ if info .BaseHasNewCommits {
115+ return info , nil
116+ }
117+
118+ // if the base's update time is before the fork, check whether the base's head is in the fork
119+ baseGitRepo , baseGitRepoCloser , err := gitrepo .RepositoryFromContextOrOpen (ctx , repo .BaseRepo )
120+ if err != nil {
121+ return nil , err
122+ }
123+ defer baseGitRepoCloser .Close ()
124+
125+ headGitRepo , headGitRepoCloser , err := gitrepo .RepositoryFromContextOrOpen (ctx , repo )
126+ if err != nil {
127+ return nil , err
128+ }
129+ defer headGitRepoCloser .Close ()
130+
131+ baseCommitID , err := baseGitRepo .ConvertToGitID (baseBranch .CommitID )
132+ if err != nil {
133+ return nil , err
134+ }
135+ headCommit , err := headGitRepo .GetCommit (forkBranch .CommitID )
136+ if err != nil {
137+ return nil , err
138+ }
139+ hasPreviousCommit , _ := headCommit .HasPreviousCommit (baseCommitID )
140+ info .BaseHasNewCommits = ! hasPreviousCommit
111141 return info , nil
112142 }
143+
113144 info .CommitsBehind , info .CommitsAhead = diff .Behind , diff .Ahead
114145 return info , nil
115146}
0 commit comments