]> source.dussan.org Git - gitea.git/commitdiff
Make wiki default branch name changable (#29603)
authorwxiaoguang <wxiaoguang@gmail.com>
Wed, 6 Mar 2024 06:26:32 +0000 (14:26 +0800)
committerGitHub <noreply@github.com>
Wed, 6 Mar 2024 06:26:32 +0000 (14:26 +0800)
Fix #29000
Fix #28685
Fix #18568

Related: #27497

And by the way fix #24036, add a Cancel button there (one line)

17 files changed:
models/migrations/migrations.go
models/migrations/v1_22/v289.go [new file with mode: 0644]
models/repo/repo.go
modules/git/repo_base_gogit.go
modules/git/repo_base_nogogit.go
options/locale/locale_en-US.ini
routers/web/repo/setting/setting.go
routers/web/repo/wiki.go
routers/web/repo/wiki_test.go
services/forms/repo_form.go
services/repository/create.go
services/repository/migrate.go
services/wiki/wiki.go
services/wiki/wiki_test.go
templates/repo/settings/options.tmpl
templates/repo/wiki/new.tmpl
templates/repo/wiki/pages.tmpl

index 9d288ec2bdf171aa3477376bf4293ec5087fdb11..d40866f3e93b3eaa627b1ffc64bb0a7d717bb151 100644 (file)
@@ -562,6 +562,8 @@ var migrations = []Migration{
        NewMigration("Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
        // v288 -> v289
        NewMigration("Add user_blocking table", v1_22.AddUserBlockingTable),
+       // v289 -> v290
+       NewMigration("Add default_wiki_branch to repository table", v1_22.AddDefaultWikiBranch),
 }
 
 // GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v1_22/v289.go b/models/migrations/v1_22/v289.go
new file mode 100644 (file)
index 0000000..e2dfc48
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import "xorm.io/xorm"
+
+func AddDefaultWikiBranch(x *xorm.Engine) error {
+       type Repository struct {
+               ID                int64
+               DefaultWikiBranch string
+       }
+       if err := x.Sync(&Repository{}); err != nil {
+               return err
+       }
+       _, err := x.Exec("UPDATE `repository` SET default_wiki_branch = 'master' WHERE (default_wiki_branch IS NULL) OR (default_wiki_branch = '')")
+       return err
+}
index f6758f1591ac69255f813c3b344baa48d424fb1a..1d17e565aef2c145ec9d1aa1261c5dec14f3421f 100644 (file)
@@ -136,6 +136,7 @@ type Repository struct {
        OriginalServiceType api.GitServiceType `xorm:"index"`
        OriginalURL         string             `xorm:"VARCHAR(2048)"`
        DefaultBranch       string
+       DefaultWikiBranch   string
 
        NumWatches          int
        NumStars            int
@@ -285,6 +286,9 @@ func (repo *Repository) AfterLoad() {
        repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
        repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
        repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
+       if repo.DefaultWikiBranch == "" {
+               repo.DefaultWikiBranch = setting.Repository.DefaultBranch
+       }
 }
 
 // LoadAttributes loads attributes of the repository.
index 3ca5eb36c6eded1e0d42ae3b224c7ecd7b62ef9c..0cd07dcdc897ec9b635c8c7cf5af50ebfd2c0e39 100644 (file)
@@ -8,11 +8,11 @@ package git
 
 import (
        "context"
-       "errors"
        "path/filepath"
 
        gitealog "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/setting"
+       "code.gitea.io/gitea/modules/util"
 
        "github.com/go-git/go-billy/v5"
        "github.com/go-git/go-billy/v5/osfs"
@@ -52,7 +52,7 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
        if err != nil {
                return nil, err
        } else if !isDir(repoPath) {
-               return nil, errors.New("no such file or directory")
+               return nil, util.NewNotExistErrorf("no such file or directory")
        }
 
        fs := osfs.New(repoPath)
index 86b6a935677536d7a5aac7dca1c16acc9f1c1714..7f6512200baeb29ecee677ba858c158128a21ced 100644 (file)
@@ -9,10 +9,10 @@ package git
 import (
        "bufio"
        "context"
-       "errors"
        "path/filepath"
 
        "code.gitea.io/gitea/modules/log"
+       "code.gitea.io/gitea/modules/util"
 )
 
 func init() {
@@ -54,7 +54,7 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
        if err != nil {
                return nil, err
        } else if !isDir(repoPath) {
-               return nil, errors.New("no such file or directory")
+               return nil, util.NewNotExistErrorf("no such file or directory")
        }
 
        // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
index 3fc74959cadacf54e9c6e7dc523d53837b82498b..59aae68cae6bbf2a982688a7d1d5aeb05a5e9576 100644 (file)
@@ -2092,6 +2092,8 @@ settings.branches.add_new_rule = Add New Rule
 settings.advanced_settings = Advanced Settings
 settings.wiki_desc = Enable Repository Wiki
 settings.use_internal_wiki = Use Built-In Wiki
+settings.default_wiki_branch_name = Default Wiki Branch Name
+settings.failed_to_change_default_wiki_branch = Failed to change the default wiki branch.
 settings.use_external_wiki = Use External Wiki
 settings.external_wiki_url = External Wiki URL
 settings.external_wiki_url_error = The external wiki URL is not a valid URL.
index 992a980d9e641e40cf27b65015e5fc020dc57262..e045e3b8dcc09e69e339f2141530449c6d4d048e 100644 (file)
@@ -488,6 +488,13 @@ func SettingsPost(ctx *context.Context) {
                        }
                }
 
+               if form.DefaultWikiBranch != "" {
+                       if err := wiki_service.ChangeDefaultWikiBranch(ctx, repo, form.DefaultWikiBranch); err != nil {
+                               log.Error("ChangeDefaultWikiBranch failed, err: %v", err)
+                               ctx.Flash.Warning(ctx.Tr("repo.settings.failed_to_change_default_wiki_branch"))
+                       }
+               }
+
                if form.EnableIssues && form.EnableExternalTracker && !unit_model.TypeExternalTracker.UnitGlobalDisabled() {
                        if !validation.IsValidExternalURL(form.ExternalTrackerURL) {
                                ctx.Flash.Error(ctx.Tr("repo.settings.external_tracker_url_error"))
index 91cf727e2c5ce65b74ba011a9d9c54032fe2188c..88b63da88d9862143dfe0f7c401b3957fe117ea5 100644 (file)
@@ -93,17 +93,32 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
 }
 
 func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
-       wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
-       if err != nil {
-               ctx.ServerError("OpenRepository", err)
-               return nil, nil, err
+       wikiGitRepo, errGitRepo := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
+       if errGitRepo != nil {
+               ctx.ServerError("OpenRepository", errGitRepo)
+               return nil, nil, errGitRepo
        }
 
-       commit, err := wikiRepo.GetBranchCommit(wiki_service.DefaultBranch)
-       if err != nil {
-               return wikiRepo, nil, err
+       commit, errCommit := wikiGitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultWikiBranch)
+       if git.IsErrNotExist(errCommit) {
+               // if the default branch recorded in database is out of sync, then re-sync it
+               gitRepoDefaultBranch, errBranch := wikiGitRepo.GetDefaultBranch()
+               if errBranch != nil {
+                       return wikiGitRepo, nil, errBranch
+               }
+               // update the default branch in the database
+               errDb := repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, DefaultWikiBranch: gitRepoDefaultBranch}, "default_wiki_branch")
+               if errDb != nil {
+                       return wikiGitRepo, nil, errDb
+               }
+               ctx.Repo.Repository.DefaultWikiBranch = gitRepoDefaultBranch
+               // retry to get the commit from the correct default branch
+               commit, errCommit = wikiGitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultWikiBranch)
        }
-       return wikiRepo, commit, nil
+       if errCommit != nil {
+               return wikiGitRepo, nil, errCommit
+       }
+       return wikiGitRepo, commit, nil
 }
 
 // wikiContentsByEntry returns the contents of the wiki page referenced by the
@@ -316,7 +331,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
        }
 
        // get commit count - wiki revisions
-       commitsCount, _ := wikiRepo.FileCommitsCount(wiki_service.DefaultBranch, pageFilename)
+       commitsCount, _ := wikiRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
        ctx.Data["CommitCount"] = commitsCount
 
        return wikiRepo, entry
@@ -368,7 +383,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
        ctx.Data["footerContent"] = ""
 
        // get commit count - wiki revisions
-       commitsCount, _ := wikiRepo.FileCommitsCount(wiki_service.DefaultBranch, pageFilename)
+       commitsCount, _ := wikiRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
        ctx.Data["CommitCount"] = commitsCount
 
        // get page
@@ -380,7 +395,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
        // get Commit Count
        commitsHistory, err := wikiRepo.CommitsByFileAndRange(
                git.CommitsByFileAndRangeOptions{
-                       Revision: wiki_service.DefaultBranch,
+                       Revision: ctx.Repo.Repository.DefaultWikiBranch,
                        File:     pageFilename,
                        Page:     page,
                })
@@ -402,20 +417,17 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
 
 func renderEditPage(ctx *context.Context) {
        wikiRepo, commit, err := findWikiRepoCommit(ctx)
-       if err != nil {
+       defer func() {
                if wikiRepo != nil {
-                       wikiRepo.Close()
+                       _ = wikiRepo.Close()
                }
+       }()
+       if err != nil {
                if !git.IsErrNotExist(err) {
                        ctx.ServerError("GetBranchCommit", err)
                }
                return
        }
-       defer func() {
-               if wikiRepo != nil {
-                       wikiRepo.Close()
-               }
-       }()
 
        // get requested pagename
        pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
@@ -584,17 +596,15 @@ func WikiPages(ctx *context.Context) {
        ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
 
        wikiRepo, commit, err := findWikiRepoCommit(ctx)
-       if err != nil {
-               if wikiRepo != nil {
-                       wikiRepo.Close()
-               }
-               return
-       }
        defer func() {
                if wikiRepo != nil {
-                       wikiRepo.Close()
+                       _ = wikiRepo.Close()
                }
        }()
+       if err != nil {
+               ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
+               return
+       }
 
        entries, err := commit.ListEntries()
        if err != nil {
index 719cca304923f2ad7a62b52b87cb084801a1e300..52e216e6a0ac275ac059756c190d3a0ca699b4ac 100644 (file)
@@ -9,6 +9,7 @@ import (
        "net/url"
        "testing"
 
+       "code.gitea.io/gitea/models/db"
        repo_model "code.gitea.io/gitea/models/repo"
        "code.gitea.io/gitea/models/unittest"
        "code.gitea.io/gitea/modules/git"
@@ -221,3 +222,32 @@ func TestWikiRaw(t *testing.T) {
                }
        }
 }
+
+func TestDefaultWikiBranch(t *testing.T) {
+       unittest.PrepareTestEnv(t)
+
+       assert.NoError(t, repo_model.UpdateRepositoryCols(db.DefaultContext, &repo_model.Repository{ID: 1, DefaultWikiBranch: "wrong-branch"}))
+
+       ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki")
+       ctx.SetParams("*", "Home")
+       contexttest.LoadRepo(t, ctx, 1)
+       assert.Equal(t, "wrong-branch", ctx.Repo.Repository.DefaultWikiBranch)
+       Wiki(ctx) // after the visiting, the out-of-sync database record will update the branch name to "master"
+       repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+       assert.Equal(t, "master", ctx.Repo.Repository.DefaultWikiBranch)
+
+       // invalid branch name should fail
+       assert.Error(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repo, "the bad name"))
+       repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+       assert.Equal(t, "master", repo.DefaultWikiBranch)
+
+       // the same branch name, should succeed (actually a no-op)
+       assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repo, "master"))
+       repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+       assert.Equal(t, "master", repo.DefaultWikiBranch)
+
+       // change to another name
+       assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repo, "main"))
+       repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+       assert.Equal(t, "main", repo.DefaultWikiBranch)
+}
index 8c3e458d2ff6ba9c6a875ff4d003d39ca4d70f1e..e45a2a16955224b7610d9694613fef84a1ec8b93 100644 (file)
@@ -133,6 +133,7 @@ type RepoSettingForm struct {
        EnableCode                            bool
        EnableWiki                            bool
        EnableExternalWiki                    bool
+       DefaultWikiBranch                     string
        ExternalWikiURL                       string
        EnableIssues                          bool
        EnableExternalTracker                 bool
index c47ce9c41364744d46a49d27355ede9d8c6dc17c..8d8c39197dece1cfb40f8daa6f1a3e9c4c7c3c63 100644 (file)
@@ -173,6 +173,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re
        }
 
        repo.DefaultBranch = setting.Repository.DefaultBranch
+       repo.DefaultWikiBranch = setting.Repository.DefaultBranch
 
        if len(opts.DefaultBranch) > 0 {
                repo.DefaultBranch = opts.DefaultBranch
@@ -240,6 +241,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
                TrustModel:                      opts.TrustModel,
                IsMirror:                        opts.IsMirror,
                DefaultBranch:                   opts.DefaultBranch,
+               DefaultWikiBranch:               setting.Repository.DefaultBranch,
                ObjectFormatName:                opts.ObjectFormatName,
        }
 
index 51fdd90f5400e047f01c006ee824ed2e087e39c2..aae2ddc1200ea6d6edd5ad9ce31927c000fc1279 100644 (file)
@@ -25,6 +25,54 @@ import (
        "code.gitea.io/gitea/modules/util"
 )
 
+func cloneWiki(ctx context.Context, u *user_model.User, opts migration.MigrateOptions, migrateTimeout time.Duration) (string, error) {
+       wikiPath := repo_model.WikiPath(u.Name, opts.RepoName)
+       wikiRemotePath := repo_module.WikiRemoteURL(ctx, opts.CloneAddr)
+       if wikiRemotePath == "" {
+               return "", nil
+       }
+
+       if err := util.RemoveAll(wikiPath); err != nil {
+               return "", fmt.Errorf("failed to remove existing wiki dir %q, err: %w", wikiPath, err)
+       }
+
+       cleanIncompleteWikiPath := func() {
+               if err := util.RemoveAll(wikiPath); err != nil {
+                       log.Error("Failed to remove incomplete wiki dir %q, err: %v", wikiPath, err)
+               }
+       }
+       if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{
+               Mirror:        true,
+               Quiet:         true,
+               Timeout:       migrateTimeout,
+               SkipTLSVerify: setting.Migrations.SkipTLSVerify,
+       }); err != nil {
+               log.Error("Clone wiki failed, err: %v", err)
+               cleanIncompleteWikiPath()
+               return "", err
+       }
+
+       if err := git.WriteCommitGraph(ctx, wikiPath); err != nil {
+               cleanIncompleteWikiPath()
+               return "", err
+       }
+
+       wikiRepo, err := git.OpenRepository(ctx, wikiPath)
+       if err != nil {
+               cleanIncompleteWikiPath()
+               return "", fmt.Errorf("failed to open wiki repo %q, err: %w", wikiPath, err)
+       }
+       defer wikiRepo.Close()
+
+       defaultBranch, err := wikiRepo.GetDefaultBranch()
+       if err != nil {
+               cleanIncompleteWikiPath()
+               return "", fmt.Errorf("failed to get wiki repo default branch for %q, err: %w", wikiPath, err)
+       }
+
+       return defaultBranch, nil
+}
+
 // MigrateRepositoryGitData starts migrating git related data after created migrating repository
 func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
        repo *repo_model.Repository, opts migration.MigrateOptions,
@@ -44,21 +92,20 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
 
        migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second
 
-       var err error
-       if err = util.RemoveAll(repoPath); err != nil {
-               return repo, fmt.Errorf("Failed to remove %s: %w", repoPath, err)
+       if err := util.RemoveAll(repoPath); err != nil {
+               return repo, fmt.Errorf("failed to remove existing repo dir %q, err: %w", repoPath, err)
        }
 
-       if err = git.Clone(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{
+       if err := git.Clone(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{
                Mirror:        true,
                Quiet:         true,
                Timeout:       migrateTimeout,
                SkipTLSVerify: setting.Migrations.SkipTLSVerify,
        }); err != nil {
                if errors.Is(err, context.DeadlineExceeded) {
-                       return repo, fmt.Errorf("Clone timed out. Consider increasing [git.timeout] MIGRATE in app.ini. Underlying Error: %w", err)
+                       return repo, fmt.Errorf("clone timed out, consider increasing [git.timeout] MIGRATE in app.ini, underlying err: %w", err)
                }
-               return repo, fmt.Errorf("Clone: %w", err)
+               return repo, fmt.Errorf("clone error: %w", err)
        }
 
        if err := git.WriteCommitGraph(ctx, repoPath); err != nil {
@@ -66,37 +113,18 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
        }
 
        if opts.Wiki {
-               wikiPath := repo_model.WikiPath(u.Name, opts.RepoName)
-               wikiRemotePath := repo_module.WikiRemoteURL(ctx, opts.CloneAddr)
-               if len(wikiRemotePath) > 0 {
-                       if err := util.RemoveAll(wikiPath); err != nil {
-                               return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err)
-                       }
-
-                       if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{
-                               Mirror:        true,
-                               Quiet:         true,
-                               Timeout:       migrateTimeout,
-                               Branch:        "master",
-                               SkipTLSVerify: setting.Migrations.SkipTLSVerify,
-                       }); err != nil {
-                               log.Warn("Clone wiki: %v", err)
-                               if err := util.RemoveAll(wikiPath); err != nil {
-                                       return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err)
-                               }
-                       } else {
-                               if err := git.WriteCommitGraph(ctx, wikiPath); err != nil {
-                                       return repo, err
-                               }
-                       }
+               defaultWikiBranch, err := cloneWiki(ctx, u, opts, migrateTimeout)
+               if err != nil {
+                       return repo, fmt.Errorf("clone wiki error: %w", err)
                }
+               repo.DefaultWikiBranch = defaultWikiBranch
        }
 
        if repo.OwnerID == u.ID {
                repo.Owner = u
        }
 
-       if err = repo_module.CheckDaemonExportOK(ctx, repo); err != nil {
+       if err := repo_module.CheckDaemonExportOK(ctx, repo); err != nil {
                return repo, fmt.Errorf("checkDaemonExportOK: %w", err)
        }
 
index 50d52d3140fe8df958b2de67732570ec607e4eae..6f1ca120b0a272e78f23bfd7d8ff726be9ed575d 100644 (file)
@@ -6,18 +6,22 @@ package wiki
 
 import (
        "context"
+       "errors"
        "fmt"
        "os"
        "strings"
 
+       "code.gitea.io/gitea/models/db"
        repo_model "code.gitea.io/gitea/models/repo"
        system_model "code.gitea.io/gitea/models/system"
        "code.gitea.io/gitea/models/unit"
        user_model "code.gitea.io/gitea/models/user"
        "code.gitea.io/gitea/modules/git"
+       "code.gitea.io/gitea/modules/gitrepo"
        "code.gitea.io/gitea/modules/log"
        repo_module "code.gitea.io/gitea/modules/repository"
        "code.gitea.io/gitea/modules/sync"
+       "code.gitea.io/gitea/modules/util"
        asymkey_service "code.gitea.io/gitea/services/asymkey"
        repo_service "code.gitea.io/gitea/services/repository"
 )
@@ -25,10 +29,7 @@ import (
 // TODO: use clustered lock (unique queue? or *abuse* cache)
 var wikiWorkingPool = sync.NewExclusivePool()
 
-const (
-       DefaultRemote = "origin"
-       DefaultBranch = "master"
-)
+const DefaultRemote = "origin"
 
 // InitWiki initializes a wiki for repository,
 // it does nothing when repository already has wiki.
@@ -41,25 +42,25 @@ func InitWiki(ctx context.Context, repo *repo_model.Repository) error {
                return fmt.Errorf("InitRepository: %w", err)
        } else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
                return fmt.Errorf("createDelegateHooks: %w", err)
-       } else if _, _, err = git.NewCommand(ctx, "symbolic-ref", "HEAD", git.BranchPrefix+DefaultBranch).RunStdString(&git.RunOpts{Dir: repo.WikiPath()}); err != nil {
-               return fmt.Errorf("unable to set default wiki branch to master: %w", err)
+       } else if _, _, err = git.NewCommand(ctx, "symbolic-ref", "HEAD").AddDynamicArguments(git.BranchPrefix + repo.DefaultWikiBranch).RunStdString(&git.RunOpts{Dir: repo.WikiPath()}); err != nil {
+               return fmt.Errorf("unable to set default wiki branch to %q: %w", repo.DefaultWikiBranch, err)
        }
        return nil
 }
 
 // prepareGitPath try to find a suitable file path with file name by the given raw wiki name.
 // return: existence, prepared file path with name, error
-func prepareGitPath(gitRepo *git.Repository, wikiPath WebPath) (bool, string, error) {
+func prepareGitPath(gitRepo *git.Repository, defaultWikiBranch string, wikiPath WebPath) (bool, string, error) {
        unescaped := string(wikiPath) + ".md"
        gitPath := WebPathToGitPath(wikiPath)
 
        // Look for both files
-       filesInIndex, err := gitRepo.LsTree(DefaultBranch, unescaped, gitPath)
+       filesInIndex, err := gitRepo.LsTree(defaultWikiBranch, unescaped, gitPath)
        if err != nil {
-               if strings.Contains(err.Error(), "Not a valid object name master") {
-                       return false, gitPath, nil
+               if strings.Contains(err.Error(), "Not a valid object name") {
+                       return false, gitPath, nil // branch doesn't exist
                }
-               log.Error("%v", err)
+               log.Error("Wiki LsTree failed, err: %v", err)
                return false, gitPath, err
        }
 
@@ -95,7 +96,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
                return fmt.Errorf("InitWiki: %w", err)
        }
 
-       hasMasterBranch := git.IsBranchExist(ctx, repo.WikiPath(), DefaultBranch)
+       hasDefaultBranch := git.IsBranchExist(ctx, repo.WikiPath(), repo.DefaultWikiBranch)
 
        basePath, err := repo_module.CreateTemporaryPath("update-wiki")
        if err != nil {
@@ -112,8 +113,8 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
                Shared: true,
        }
 
-       if hasMasterBranch {
-               cloneOpts.Branch = DefaultBranch
+       if hasDefaultBranch {
+               cloneOpts.Branch = repo.DefaultWikiBranch
        }
 
        if err := git.Clone(ctx, repo.WikiPath(), basePath, cloneOpts); err != nil {
@@ -128,14 +129,14 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
        }
        defer gitRepo.Close()
 
-       if hasMasterBranch {
+       if hasDefaultBranch {
                if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
                        log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
                        return fmt.Errorf("fnable to read HEAD tree to index in: %s %w", basePath, err)
                }
        }
 
-       isWikiExist, newWikiPath, err := prepareGitPath(gitRepo, newWikiName)
+       isWikiExist, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, newWikiName)
        if err != nil {
                return err
        }
@@ -151,7 +152,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
                isOldWikiExist := true
                oldWikiPath := newWikiPath
                if oldWikiName != newWikiName {
-                       isOldWikiExist, oldWikiPath, err = prepareGitPath(gitRepo, oldWikiName)
+                       isOldWikiExist, oldWikiPath, err = prepareGitPath(gitRepo, repo.DefaultWikiBranch, oldWikiName)
                        if err != nil {
                                return err
                        }
@@ -200,7 +201,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
        } else {
                commitTreeOpts.NoGPGSign = true
        }
-       if hasMasterBranch {
+       if hasDefaultBranch {
                commitTreeOpts.Parents = []string{"HEAD"}
        }
 
@@ -212,7 +213,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
 
        if err := git.Push(gitRepo.Ctx, basePath, git.PushOptions{
                Remote: DefaultRemote,
-               Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, DefaultBranch),
+               Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, repo.DefaultWikiBranch),
                Env: repo_module.FullPushingEnvironment(
                        doer,
                        doer,
@@ -269,7 +270,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
        if err := git.Clone(ctx, repo.WikiPath(), basePath, git.CloneRepoOptions{
                Bare:   true,
                Shared: true,
-               Branch: DefaultBranch,
+               Branch: repo.DefaultWikiBranch,
        }); err != nil {
                log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
                return fmt.Errorf("failed to clone repository: %s (%w)", repo.FullName(), err)
@@ -287,7 +288,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
                return fmt.Errorf("unable to read HEAD tree to index in: %s %w", basePath, err)
        }
 
-       found, wikiPath, err := prepareGitPath(gitRepo, wikiName)
+       found, wikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, wikiName)
        if err != nil {
                return err
        }
@@ -331,7 +332,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
 
        if err := git.Push(gitRepo.Ctx, basePath, git.PushOptions{
                Remote: DefaultRemote,
-               Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, DefaultBranch),
+               Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, repo.DefaultWikiBranch),
                Env: repo_module.FullPushingEnvironment(
                        doer,
                        doer,
@@ -358,3 +359,37 @@ func DeleteWiki(ctx context.Context, repo *repo_model.Repository) error {
        system_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath())
        return nil
 }
+
+func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, newBranch string) error {
+       if !git.IsValidRefPattern(newBranch) {
+               return fmt.Errorf("invalid branch name: %s", newBranch)
+       }
+       return db.WithTx(ctx, func(ctx context.Context) error {
+               repo.DefaultWikiBranch = newBranch
+               if err := repo_model.UpdateRepositoryCols(ctx, repo, "default_wiki_branch"); err != nil {
+                       return fmt.Errorf("unable to update database: %w", err)
+               }
+
+               gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo)
+               if errors.Is(err, util.ErrNotExist) {
+                       return nil // no git repo on storage, no need to do anything else
+               } else if err != nil {
+                       return fmt.Errorf("unable to open repository: %w", err)
+               }
+               defer gitRepo.Close()
+
+               oldDefBranch, err := gitRepo.GetDefaultBranch()
+               if err != nil {
+                       return fmt.Errorf("unable to get default branch: %w", err)
+               }
+               if oldDefBranch == newBranch {
+                       return nil
+               }
+
+               err = gitRepo.RenameBranch(oldDefBranch, newBranch)
+               if err != nil {
+                       return fmt.Errorf("unable to rename default branch: %w", err)
+               }
+               return nil
+       })
+}
index 59c77060f2c2716f80925f5033dd289014746101..0a18cffa25310ceb2ab38f4538e8e6d8da899679 100644 (file)
@@ -170,7 +170,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
                                return
                        }
                        defer gitRepo.Close()
-                       masterTree, err := gitRepo.GetTree(DefaultBranch)
+                       masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
                        assert.NoError(t, err)
                        gitPath := WebPathToGitPath(webPath)
                        entry, err := masterTree.GetTreeEntryByPath(gitPath)
@@ -215,7 +215,7 @@ func TestRepository_EditWikiPage(t *testing.T) {
                // Now need to show that the page has been added:
                gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
                assert.NoError(t, err)
-               masterTree, err := gitRepo.GetTree(DefaultBranch)
+               masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
                assert.NoError(t, err)
                gitPath := WebPathToGitPath(webPath)
                entry, err := masterTree.GetTreeEntryByPath(gitPath)
@@ -242,7 +242,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
                return
        }
        defer gitRepo.Close()
-       masterTree, err := gitRepo.GetTree(DefaultBranch)
+       masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
        assert.NoError(t, err)
        gitPath := WebPathToGitPath("Home")
        _, err = masterTree.GetTreeEntryByPath(gitPath)
@@ -280,7 +280,7 @@ func TestPrepareWikiFileName(t *testing.T) {
        for _, tt := range tests {
                t.Run(tt.name, func(t *testing.T) {
                        webPath := UserTitleToWebPath("", tt.arg)
-                       existence, newWikiPath, err := prepareGitPath(gitRepo, webPath)
+                       existence, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, webPath)
                        if (err != nil) != tt.wantErr {
                                assert.NoError(t, err)
                                return
@@ -312,7 +312,7 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) {
        }
        defer gitRepo.Close()
 
-       existence, newWikiPath, err := prepareGitPath(gitRepo, "Home")
+       existence, newWikiPath, err := prepareGitPath(gitRepo, "master", "Home")
        assert.False(t, existence)
        assert.NoError(t, err)
        assert.EqualValues(t, "Home.md", newWikiPath)
index 0de42b34ea8988272365b155c855f7a7deec66c5..a699396a84b326575145d25ca4a1b92961867f9e 100644 (file)
                                                        <label>{{ctx.Locale.Tr "repo.settings.use_internal_wiki"}}</label>
                                                </div>
                                        </div>
+                                       <div class="inline field gt-pl-4">
+                                               <label>{{ctx.Locale.Tr "repo.settings.default_wiki_branch_name"}}</label>
+                                               <input name="default_wiki_branch" value="{{.Repository.DefaultWikiBranch}}">
+                                       </div>
                                        <div class="field">
                                                <div class="ui radio checkbox{{if $isExternalWikiGlobalDisabled}} disabled{{end}}"{{if $isExternalWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
                                                        <input class="enable-system-radio" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.UnitEnabled $.Context $.UnitTypeExternalWiki}}checked{{end}}>
index ff31df0c32db5596687cd26db9bed64ca9e99db2..640f8ca9cd6076cb7c674f4105a11901dda43ad4 100644 (file)
@@ -36,9 +36,8 @@
                        </div>
                        <div class="divider"></div>
                        <div class="text right">
-                               <button class="ui primary button">
-                                       {{ctx.Locale.Tr "repo.wiki.save_page"}}
-                               </button>
+                               <a class="ui basic cancel button" href="{{.Link}}">{{ctx.Locale.Tr "cancel"}}</a>
+                               <button class="ui primary button">{{ctx.Locale.Tr "repo.wiki.save_page"}}</button>
                        </div>
                </form>
        </div>
index 22eb2619f919092472fb6eeb757aaa410f75898a..cace0d48e00838a34ae1673021bd0d24d9a0534e 100644 (file)
@@ -10,6 +10,7 @@
                                {{end}}
                        </span>
                </h2>
+               {{if .IsRepositoryAdmin}}<div>{{ctx.Locale.Tr "repo.default_branch"}}: {{.Repository.DefaultWikiBranch}}</div>{{end}}
                <table class="ui table wiki-pages-list">
                        <tbody>
                                {{range .Pages}}