From 3c46a3deb3b779d8a8a2fc5cac4cdf0128974eb9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 6 Mar 2026 07:26:34 -0800 Subject: [PATCH] Fix bug when pushing mirror with wiki (#36795) (#36807) Fix #36736 Backport #36795 Co-authored-by: ChristopherHX --- cmd/hook.go | 4 +++ routers/private/hook_pre_receive.go | 6 +++- tests/integration/mirror_push_test.go | 44 +++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/cmd/hook.go b/cmd/hook.go index 37fdb92770..9aeabe61ed 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -205,6 +205,7 @@ Gitea or set your environment appropriately.`, "") PullRequestID: prID, DeployKeyID: deployKeyID, ActionPerm: int(actionPerm), + IsWiki: isWiki, } scanner := bufio.NewScanner(os.Stdin) @@ -366,6 +367,7 @@ Gitea or set your environment appropriately.`, "") GitPushOptions: pushOptions(), PullRequestID: prID, PushTrigger: repo_module.PushTrigger(os.Getenv(repo_module.EnvPushTrigger)), + IsWiki: isWiki, } oldCommitIDs := make([]string, hookBatchSize) newCommitIDs := make([]string, hookBatchSize) @@ -513,6 +515,7 @@ Gitea or set your environment appropriately.`, "") reader := bufio.NewReader(os.Stdin) repoUser := os.Getenv(repo_module.EnvRepoUsername) + isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki)) repoName := os.Getenv(repo_module.EnvRepoName) pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64) pusherName := os.Getenv(repo_module.EnvPusherName) @@ -590,6 +593,7 @@ Gitea or set your environment appropriately.`, "") UserName: pusherName, UserID: pusherID, GitPushOptions: make(map[string]string), + IsWiki: isWiki, } hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize) hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize) diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index 99a0b450d7..bd95edfff2 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -149,7 +149,11 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r gitRepo := ctx.Repo.GitRepo objectFormat := ctx.Repo.GetObjectFormat() - if branchName == repo.DefaultBranch && newCommitID == objectFormat.EmptyObjectID().String() { + defaultBranch := repo.DefaultBranch + if ctx.opts.IsWiki && repo.DefaultWikiBranch != "" { + defaultBranch = repo.DefaultWikiBranch + } + if branchName == defaultBranch && newCommitID == objectFormat.EmptyObjectID().String() { log.Warn("Forbidden: Branch: %s is the default branch in %-v and cannot be deleted", branchName, repo) ctx.JSON(http.StatusForbidden, private.Response{ UserMsg: fmt.Sprintf("branch %s is the default branch and cannot be deleted", branchName), diff --git a/tests/integration/mirror_push_test.go b/tests/integration/mirror_push_test.go index c468228b82..364d12b613 100644 --- a/tests/integration/mirror_push_test.go +++ b/tests/integration/mirror_push_test.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/services/migrations" mirror_service "code.gitea.io/gitea/services/mirror" repo_service "code.gitea.io/gitea/services/repository" + wiki_service "code.gitea.io/gitea/services/wiki" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" @@ -29,6 +30,10 @@ func TestMirrorPush(t *testing.T) { onGiteaRun(t, testMirrorPush) } +func TestMirrorPushWikiDefaultBranchMismatch(t *testing.T) { + onGiteaRun(t, testMirrorPushWikiDefaultBranchMismatch) +} + func testMirrorPush(t *testing.T, u *url.URL) { setting.Migrations.AllowLocalNetworks = true assert.NoError(t, migrations.Init()) @@ -77,6 +82,45 @@ func testMirrorPush(t *testing.T, u *url.URL) { assert.Empty(t, mirrors) } +func testMirrorPushWikiDefaultBranchMismatch(t *testing.T, u *url.URL) { + setting.Migrations.AllowLocalNetworks = true + assert.NoError(t, migrations.Init()) + + _ = db.TruncateBeans(t.Context(), &repo_model.PushMirror{}) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + srcRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + + mirrorRepo, err := repo_service.CreateRepositoryDirectly(t.Context(), user, user, repo_service.CreateRepoOptions{ + Name: "test-push-mirror-wiki", + }, true) + assert.NoError(t, err) + + assert.NoError(t, wiki_service.AddWikiPage(t.Context(), user, mirrorRepo, wiki_service.WebPath("Home"), "Mirror wiki content", "init wiki")) + + mirrorRepo.DefaultBranch = "mirror-head" + assert.NoError(t, repo_model.UpdateRepositoryColsNoAutoTime(t.Context(), mirrorRepo, "default_branch")) + + gitRepo, err := gitrepo.OpenRepository(t.Context(), mirrorRepo.WikiStorageRepo()) + assert.NoError(t, err) + defer gitRepo.Close() + + wikiCommitID, err := gitrepo.GetBranchCommitID(t.Context(), mirrorRepo.WikiStorageRepo(), mirrorRepo.DefaultWikiBranch) + assert.NoError(t, err) + assert.NoError(t, gitRepo.CreateBranch("mirror-head", wikiCommitID)) + + session := loginUser(t, user.Name) + + pushMirrorURL := fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(user.Name), url.PathEscape(mirrorRepo.Name)) + testCreatePushMirror(t, session, user.Name, srcRepo.Name, pushMirrorURL, user.LowerName, userPassword, "0") + + mirrors, _, err := repo_model.GetPushMirrorsByRepoID(t.Context(), srcRepo.ID, db.ListOptions{}) + assert.NoError(t, err) + assert.Len(t, mirrors, 1) + + ok := mirror_service.SyncPushMirror(t.Context(), mirrors[0].ID) + assert.True(t, ok) +} + func testCreatePushMirror(t *testing.T, session *TestSession, owner, repo, address, username, password, interval string) { req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings", url.PathEscape(owner), url.PathEscape(repo)), map[string]string{ "_csrf": GetUserCSRFToken(t, session),