From 7668e7c00d750350652abe2af133ee1336f50dc5 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Wed, 26 Aug 2026 01:52:21 +0800 Subject: [PATCH] chore: repo compare link (#39088) Signed-off-by: silverwind Co-authored-by: silverwind --- custom/conf/app.example.ini | 1 - routers/web/repo/pull.go | 17 +++++++++-------- services/context/repo.go | 16 +++++++++++++--- services/context/repo_test.go | 15 +++++++++------ 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 9ede26ec0c1..86631be7007 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1128,7 +1128,6 @@ LEVEL = Info ;ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT = true ;; Allow to fork repositories into the same owner (user or organization) -;; This feature is experimental, not fully tested, and may be changed in the future ;ALLOW_FORK_INTO_SAME_OWNER = false ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 82f171176c1..9caba3ae3a4 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1297,18 +1297,19 @@ func stopTimerIfAvailable(ctx *context.Context, user *user_model.User, issue *is } func PullsNewRedirect(ctx *context.Context) { - branch := ctx.PathParam("*") - redirectRepo := ctx.Repo.Repository - repo := ctx.Repo.Repository - if repo.IsFork { - if err := repo.GetBaseRepo(ctx); err != nil { + branchName := ctx.PathParam("*") + baseRepo, headRepo := ctx.Repo.Repository, ctx.Repo.Repository + if headRepo.IsFork { + if err := headRepo.GetBaseRepo(ctx); err != nil { ctx.ServerError("GetBaseRepo", err) return } - redirectRepo = repo.BaseRepo - branch = context.CompareHeadRef(repo, branch) + baseRepo = headRepo.BaseRepo } - ctx.Redirect(fmt.Sprintf("%s/compare/%s...%s?expand=1", redirectRepo.Link(), util.PathEscapeSegments(redirectRepo.DefaultBranch), util.PathEscapeSegments(branch))) + ctx.Redirect(fmt.Sprintf("%s/compare/%s...%s?expand=1", baseRepo.Link(), + util.PathEscapeSegments(baseRepo.DefaultBranch), + util.PathEscapeSegments(context.CompareHeadRef(baseRepo, headRepo, branchName)), + )) } // CompareAndPullRequestPost response for creating pull request diff --git a/services/context/repo.go b/services/context/repo.go index 61ffbb22f79..0d0fafc4a64 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -65,14 +65,24 @@ func (prc *PullRequestContext) CanCreateNewPull() bool { } // CompareHeadRef formats the head side of a compare link, "owner/repo:branch" is only needed when a fork can share its base repo's owner -func CompareHeadRef(headRepo *repo_model.Repository, headBranch string) string { - return util.Iif(setting.Repository.AllowForkIntoSameOwner, headRepo.FullName(), headRepo.OwnerName) + ":" + headBranch +func CompareHeadRef(baseRepo, headRepo *repo_model.Repository, headBranch string) string { + if baseRepo.ID == headRepo.ID /* same repo */ { + return headBranch + } else if baseRepo.OwnerID == headRepo.OwnerID /* same owner */ { + return headRepo.FullName() + ":" + headBranch + } + // not the same owner: if there can be multiple forks in one owner, we still need the full name + if setting.Repository.AllowForkIntoSameOwner { + return headRepo.FullName() + ":" + headBranch + } + // if there is only one fork in the different owner, we only need the owner's name for the head ref + return headRepo.OwnerName + ":" + headBranch } func (prc *PullRequestContext) MakeDefaultCompareLink(headBranch string) string { return prc.baseRepo.Link() + "/compare/" + util.PathEscapeSegments(prc.DefaultTargetBranch()) + "..." + - util.PathEscapeSegments(util.Iif(prc.SameRepo(), headBranch, CompareHeadRef(prc.headRepo, headBranch))) + util.PathEscapeSegments(CompareHeadRef(prc.baseRepo, prc.headRepo, headBranch)) } func (prc *PullRequestContext) DefaultTargetBranch() string { diff --git a/services/context/repo_test.go b/services/context/repo_test.go index 868ce7783d3..afdfa760a9e 100644 --- a/services/context/repo_test.go +++ b/services/context/repo_test.go @@ -14,12 +14,15 @@ import ( ) func TestCompareHeadRef(t *testing.T) { - defer test.MockVariableValue(&setting.Repository.AllowForkIntoSameOwner)() - headRepo := &repo_model.Repository{OwnerName: "user", Name: "fork"} - - setting.Repository.AllowForkIntoSameOwner = false - assert.Equal(t, "user:my-branch", CompareHeadRef(headRepo, "my-branch")) + defer test.MockVariableValue(&setting.Repository.AllowForkIntoSameOwner, false)() + baseRepo := &repo_model.Repository{ID: 1, OwnerID: 100, OwnerName: "base-owner", Name: "base-repo"} + sameRepo := baseRepo + sameOwner := &repo_model.Repository{ID: 2, OwnerID: 100, OwnerName: "head-owner", Name: "head-repo"} + diffOwner := &repo_model.Repository{ID: 2, OwnerID: 101, OwnerName: "head-owner", Name: "head-repo"} + assert.Equal(t, "my-branch", CompareHeadRef(baseRepo, sameRepo, "my-branch")) + assert.Equal(t, "head-owner/head-repo:my-branch", CompareHeadRef(baseRepo, sameOwner, "my-branch")) + assert.Equal(t, "head-owner:my-branch", CompareHeadRef(baseRepo, diffOwner, "my-branch")) setting.Repository.AllowForkIntoSameOwner = true - assert.Equal(t, "user/fork:my-branch", CompareHeadRef(headRepo, "my-branch")) + assert.Equal(t, "head-owner/head-repo:my-branch", CompareHeadRef(baseRepo, diffOwner, "my-branch")) }