@@ -12,17 +12,20 @@ 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"
17+ "code.gitea.io/gitea/modules/reqctx"
1618 "code.gitea.io/gitea/modules/util"
1719 "code.gitea.io/gitea/services/pull"
1820)
1921
2022type UpstreamDivergingInfo struct {
21- BaseIsNewer bool
22- CommitsBehind int
23- CommitsAhead int
23+ BaseHasNewCommits bool
24+ CommitsBehind int
25+ CommitsAhead int
2426}
2527
28+ // MergeUpstream merges the base repository's default branch into the fork repository's current branch.
2629func MergeUpstream (ctx context.Context , doer * user_model.User , repo * repo_model.Repository , branch string ) (mergeStyle string , err error ) {
2730 if err = repo .MustNotBeArchived (); err != nil {
2831 return "" , err
@@ -32,7 +35,7 @@ func MergeUpstream(ctx context.Context, doer *user_model.User, repo *repo_model.
3235 }
3336 err = git .Push (ctx , repo .BaseRepo .RepoPath (), git.PushOptions {
3437 Remote : repo .RepoPath (),
35- Branch : fmt .Sprintf ("%s:%s" , branch , branch ),
38+ Branch : fmt .Sprintf ("%s:%s" , repo . BaseRepo . DefaultBranch , branch ),
3639 Env : repo_module .PushingEnvironment (doer , repo ),
3740 })
3841 if err == nil {
@@ -64,7 +67,7 @@ func MergeUpstream(ctx context.Context, doer *user_model.User, repo *repo_model.
6467 BaseRepoID : repo .BaseRepo .ID ,
6568 BaseRepo : repo .BaseRepo ,
6669 HeadBranch : branch , // maybe HeadCommitID is not needed
67- BaseBranch : branch ,
70+ BaseBranch : repo . BaseRepo . DefaultBranch ,
6871 }
6972 fakeIssue .PullRequest = fakePR
7073 err = pull .Update (ctx , fakePR , doer , "merge upstream" , false )
@@ -74,7 +77,8 @@ func MergeUpstream(ctx context.Context, doer *user_model.User, repo *repo_model.
7477 return "merge" , nil
7578}
7679
77- func GetUpstreamDivergingInfo (ctx context.Context , repo * repo_model.Repository , branch string ) (* UpstreamDivergingInfo , error ) {
80+ // GetUpstreamDivergingInfo returns the information about the divergence between the fork repository's branch and the base repository's default branch.
81+ func GetUpstreamDivergingInfo (ctx reqctx.RequestContext , repo * repo_model.Repository , branch string ) (* UpstreamDivergingInfo , error ) {
7882 if ! repo .IsFork {
7983 return nil , util .NewInvalidArgumentErrorf ("repo is not a fork" )
8084 }
@@ -92,7 +96,7 @@ func GetUpstreamDivergingInfo(ctx context.Context, repo *repo_model.Repository,
9296 return nil , err
9397 }
9498
95- baseBranch , err := git_model .GetBranch (ctx , repo .BaseRepo .ID , branch )
99+ baseBranch , err := git_model .GetBranch (ctx , repo .BaseRepo .ID , repo . BaseRepo . DefaultBranch )
96100 if err != nil {
97101 return nil , err
98102 }
@@ -102,14 +106,39 @@ func GetUpstreamDivergingInfo(ctx context.Context, repo *repo_model.Repository,
102106 return info , nil
103107 }
104108
105- // TODO: if the fork repo has new commits, this call will fail:
109+ // if the fork repo has new commits, this call will fail because they are not in the base repo
106110 // 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
111+ // so at the moment, we first check the update time, then check whether the fork branch has base's head
108112 diff , err := git .GetDivergingCommits (ctx , repo .BaseRepo .RepoPath (), baseBranch .CommitID , forkBranch .CommitID )
109113 if err != nil {
110- info .BaseIsNewer = baseBranch .UpdatedUnix > forkBranch .UpdatedUnix
114+ info .BaseHasNewCommits = baseBranch .UpdatedUnix > forkBranch .UpdatedUnix
115+ if info .BaseHasNewCommits {
116+ return info , nil
117+ }
118+
119+ // if the base's update time is before the fork, check whether the base's head is in the fork
120+ baseGitRepo , err := gitrepo .RepositoryFromRequestContextOrOpen (ctx , repo .BaseRepo )
121+ if err != nil {
122+ return nil , err
123+ }
124+ headGitRepo , err := gitrepo .RepositoryFromRequestContextOrOpen (ctx , repo )
125+ if err != nil {
126+ return nil , err
127+ }
128+
129+ baseCommitID , err := baseGitRepo .ConvertToGitID (baseBranch .CommitID )
130+ if err != nil {
131+ return nil , err
132+ }
133+ headCommit , err := headGitRepo .GetCommit (forkBranch .CommitID )
134+ if err != nil {
135+ return nil , err
136+ }
137+ hasPreviousCommit , _ := headCommit .HasPreviousCommit (baseCommitID )
138+ info .BaseHasNewCommits = ! hasPreviousCommit
111139 return info , nil
112140 }
141+
113142 info .CommitsBehind , info .CommitsAhead = diff .Behind , diff .Ahead
114143 return info , nil
115144}
0 commit comments