diff --git a/services/repository/branch.go b/services/repository/branch.go index fe411ae2bc2b0..280efb8ee3983 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -672,12 +672,20 @@ func GetBranchDivergingInfo(ctx reqctx.RequestContext, baseRepo, headRepo *repo_ // so at the moment, we first check the update time, then check whether the fork branch has base's head diff, err := git.GetDivergingCommits(ctx, baseRepo.RepoPath(), baseGitBranch.CommitID, headGitBranch.CommitID) if err != nil { + info.BaseIsNewer = baseGitBranch.UpdatedUnix > headGitBranch.UpdatedUnix + if headRepo.IsFork && info.BaseIsNewer { + return info, nil + } // if the base's update time is before the fork, check whether the base's head is in the fork + baseGitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, baseRepo) + if err != nil { + return nil, err + } headGitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, headRepo) if err != nil { return nil, err } - baseCommitID, err := headGitRepo.ConvertToGitID(baseGitBranch.CommitID) + baseCommitID, err := baseGitRepo.ConvertToGitID(baseGitBranch.CommitID) if err != nil { return nil, err } @@ -685,12 +693,8 @@ func GetBranchDivergingInfo(ctx reqctx.RequestContext, baseRepo, headRepo *repo_ if err != nil { return nil, err } - hasPreviousCommit, err := headCommit.HasPreviousCommit(baseCommitID) + hasPreviousCommit, _ := headCommit.HasPreviousCommit(baseCommitID) info.BaseIsNewer = !hasPreviousCommit - // make update time as last resort for divergence comparison - if err != nil { - info.BaseIsNewer = baseGitBranch.UpdatedUnix > headGitBranch.UpdatedUnix - } return info, nil } diff --git a/tests/integration/repo_merge_upstream_test.go b/tests/integration/repo_merge_upstream_test.go index 19992dc19d358..e3e423c51d5d2 100644 --- a/tests/integration/repo_merge_upstream_test.go +++ b/tests/integration/repo_merge_upstream_test.go @@ -4,7 +4,6 @@ package integration import ( - "encoding/base64" "fmt" "net/http" "net/url" @@ -13,6 +12,8 @@ import ( "time" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -36,7 +37,6 @@ func TestRepoMergeUpstream(t *testing.T) { require.Equal(t, exp, resp.Body.String()) } - baseSession := loginUser(t, baseUser.Name) session := loginUser(t, forkUser.Name) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) @@ -60,7 +60,7 @@ func TestRepoMergeUpstream(t *testing.T) { t.Run("HeadBeforeBase", func(t *testing.T) { // add a file in base repo - testAPINewFile(t, baseSession, baseRepo.OwnerName, baseRepo.Name, "master", "new-file.txt", "test-content-1") + require.NoError(t, createOrReplaceFileInBranch(baseUser, baseRepo, "new-file.txt", "master", "test-content-1")) // the repo shows a prompt to "sync fork" var mergeUpstreamLink string @@ -83,21 +83,14 @@ func TestRepoMergeUpstream(t *testing.T) { t.Run("BaseChangeAfterHeadChange", func(t *testing.T) { // update the files: base first, head later, and check the prompt - testAPINewFile(t, session, forkRepo.OwnerName, forkRepo.Name, "fork-branch", "new-file-other.txt", "test-content-other") - baseUserToken := getTokenForLoggedInUser(t, baseSession, auth_model.AccessTokenScopeWriteRepository) - req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", baseRepo.OwnerName, baseRepo.Name, "new-file.txt"), &api.UpdateFileOptions{ - DeleteFileOptions: api.DeleteFileOptions{ - FileOptions: api.FileOptions{ - BranchName: "master", - NewBranchName: "master", - Message: "Update new-file.txt", - }, - SHA: "a4007b6679563f949751ed31bb371fdfb3194446", - }, - ContentBase64: base64.StdEncoding.EncodeToString([]byte("test-content-2")), - }). - AddTokenAuth(baseUserToken) - MakeRequest(t, req, http.StatusOK) + require.NoError(t, createOrReplaceFileInBranch(baseUser, baseRepo, "new-file.txt", "master", "test-content-2")) + require.NoError(t, createOrReplaceFileInBranch(forkUser, forkRepo, "new-file-other.txt", "fork-branch", "test-content-other")) + + // make sure the base branch's update time is before the fork, to make it test the complete logic + baseBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: baseRepo.ID, Name: "master"}) + forkBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: forkRepo.ID, Name: "fork-branch"}) + _, err := db.GetEngine(db.DefaultContext).ID(forkBranch.ID).Update(&git_model.Branch{UpdatedUnix: baseBranch.UpdatedUnix + 1}) + require.NoError(t, err) // the repo shows a prompt to "sync fork" require.Eventually(t, func() bool {