mirror of
https://github.com/go-gitea/gitea
synced 2024-11-24 18:53:15 +01:00
Make wiki default branch name changable (#29603)
Fix #29000 Fix #28685 Fix #18568 Related: #27497 And by the way fix #24036, add a Cancel button there (one line)
This commit is contained in:
parent
da15d6127c
commit
5cddab4f74
17 changed files with 232 additions and 89 deletions
|
@ -562,6 +562,8 @@ var migrations = []Migration{
|
||||||
NewMigration("Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
|
NewMigration("Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
|
||||||
// v288 -> v289
|
// v288 -> v289
|
||||||
NewMigration("Add user_blocking table", v1_22.AddUserBlockingTable),
|
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
|
// GetCurrentDBVersion returns the current db version
|
||||||
|
|
18
models/migrations/v1_22/v289.go
Normal file
18
models/migrations/v1_22/v289.go
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -136,6 +136,7 @@ type Repository struct {
|
||||||
OriginalServiceType api.GitServiceType `xorm:"index"`
|
OriginalServiceType api.GitServiceType `xorm:"index"`
|
||||||
OriginalURL string `xorm:"VARCHAR(2048)"`
|
OriginalURL string `xorm:"VARCHAR(2048)"`
|
||||||
DefaultBranch string
|
DefaultBranch string
|
||||||
|
DefaultWikiBranch string
|
||||||
|
|
||||||
NumWatches int
|
NumWatches int
|
||||||
NumStars int
|
NumStars int
|
||||||
|
@ -285,6 +286,9 @@ func (repo *Repository) AfterLoad() {
|
||||||
repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
|
repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
|
||||||
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
||||||
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
|
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
|
||||||
|
if repo.DefaultWikiBranch == "" {
|
||||||
|
repo.DefaultWikiBranch = setting.Repository.DefaultBranch
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttributes loads attributes of the repository.
|
// LoadAttributes loads attributes of the repository.
|
||||||
|
|
|
@ -8,11 +8,11 @@ package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
gitealog "code.gitea.io/gitea/modules/log"
|
gitealog "code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"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"
|
||||||
"github.com/go-git/go-billy/v5/osfs"
|
"github.com/go-git/go-billy/v5/osfs"
|
||||||
|
@ -52,7 +52,7 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !isDir(repoPath) {
|
} 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)
|
fs := osfs.New(repoPath)
|
||||||
|
|
|
@ -9,10 +9,10 @@ package git
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -54,7 +54,7 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !isDir(repoPath) {
|
} 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!
|
// 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!
|
||||||
|
|
|
@ -2092,6 +2092,8 @@ settings.branches.add_new_rule = Add New Rule
|
||||||
settings.advanced_settings = Advanced Settings
|
settings.advanced_settings = Advanced Settings
|
||||||
settings.wiki_desc = Enable Repository Wiki
|
settings.wiki_desc = Enable Repository Wiki
|
||||||
settings.use_internal_wiki = Use Built-In 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.use_external_wiki = Use External Wiki
|
||||||
settings.external_wiki_url = External Wiki URL
|
settings.external_wiki_url = External Wiki URL
|
||||||
settings.external_wiki_url_error = The external wiki URL is not a valid URL.
|
settings.external_wiki_url_error = The external wiki URL is not a valid URL.
|
||||||
|
|
|
@ -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 form.EnableIssues && form.EnableExternalTracker && !unit_model.TypeExternalTracker.UnitGlobalDisabled() {
|
||||||
if !validation.IsValidExternalURL(form.ExternalTrackerURL) {
|
if !validation.IsValidExternalURL(form.ExternalTrackerURL) {
|
||||||
ctx.Flash.Error(ctx.Tr("repo.settings.external_tracker_url_error"))
|
ctx.Flash.Error(ctx.Tr("repo.settings.external_tracker_url_error"))
|
||||||
|
|
|
@ -93,17 +93,32 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
|
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
|
||||||
wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
wikiGitRepo, errGitRepo := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if errGitRepo != nil {
|
||||||
ctx.ServerError("OpenRepository", err)
|
ctx.ServerError("OpenRepository", errGitRepo)
|
||||||
return nil, nil, err
|
return nil, nil, errGitRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
commit, err := wikiRepo.GetBranchCommit(wiki_service.DefaultBranch)
|
commit, errCommit := wikiGitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultWikiBranch)
|
||||||
if err != nil {
|
if git.IsErrNotExist(errCommit) {
|
||||||
return wikiRepo, nil, err
|
// 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
|
// 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
|
// get commit count - wiki revisions
|
||||||
commitsCount, _ := wikiRepo.FileCommitsCount(wiki_service.DefaultBranch, pageFilename)
|
commitsCount, _ := wikiRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
|
||||||
ctx.Data["CommitCount"] = commitsCount
|
ctx.Data["CommitCount"] = commitsCount
|
||||||
|
|
||||||
return wikiRepo, entry
|
return wikiRepo, entry
|
||||||
|
@ -368,7 +383,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
|
||||||
ctx.Data["footerContent"] = ""
|
ctx.Data["footerContent"] = ""
|
||||||
|
|
||||||
// get commit count - wiki revisions
|
// get commit count - wiki revisions
|
||||||
commitsCount, _ := wikiRepo.FileCommitsCount(wiki_service.DefaultBranch, pageFilename)
|
commitsCount, _ := wikiRepo.FileCommitsCount(ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
|
||||||
ctx.Data["CommitCount"] = commitsCount
|
ctx.Data["CommitCount"] = commitsCount
|
||||||
|
|
||||||
// get page
|
// get page
|
||||||
|
@ -380,7 +395,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
|
||||||
// get Commit Count
|
// get Commit Count
|
||||||
commitsHistory, err := wikiRepo.CommitsByFileAndRange(
|
commitsHistory, err := wikiRepo.CommitsByFileAndRange(
|
||||||
git.CommitsByFileAndRangeOptions{
|
git.CommitsByFileAndRangeOptions{
|
||||||
Revision: wiki_service.DefaultBranch,
|
Revision: ctx.Repo.Repository.DefaultWikiBranch,
|
||||||
File: pageFilename,
|
File: pageFilename,
|
||||||
Page: page,
|
Page: page,
|
||||||
})
|
})
|
||||||
|
@ -402,20 +417,17 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
|
||||||
|
|
||||||
func renderEditPage(ctx *context.Context) {
|
func renderEditPage(ctx *context.Context) {
|
||||||
wikiRepo, commit, err := findWikiRepoCommit(ctx)
|
wikiRepo, commit, err := findWikiRepoCommit(ctx)
|
||||||
if err != nil {
|
defer func() {
|
||||||
if wikiRepo != nil {
|
if wikiRepo != nil {
|
||||||
wikiRepo.Close()
|
_ = wikiRepo.Close()
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
if !git.IsErrNotExist(err) {
|
if !git.IsErrNotExist(err) {
|
||||||
ctx.ServerError("GetBranchCommit", err)
|
ctx.ServerError("GetBranchCommit", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if wikiRepo != nil {
|
|
||||||
wikiRepo.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// get requested pagename
|
// get requested pagename
|
||||||
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
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
|
ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
|
||||||
|
|
||||||
wikiRepo, commit, err := findWikiRepoCommit(ctx)
|
wikiRepo, commit, err := findWikiRepoCommit(ctx)
|
||||||
if err != nil {
|
|
||||||
if wikiRepo != nil {
|
|
||||||
wikiRepo.Close()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if wikiRepo != nil {
|
if wikiRepo != nil {
|
||||||
wikiRepo.Close()
|
_ = wikiRepo.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
entries, err := commit.ListEntries()
|
entries, err := commit.ListEntries()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"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)
|
||||||
|
}
|
||||||
|
|
|
@ -133,6 +133,7 @@ type RepoSettingForm struct {
|
||||||
EnableCode bool
|
EnableCode bool
|
||||||
EnableWiki bool
|
EnableWiki bool
|
||||||
EnableExternalWiki bool
|
EnableExternalWiki bool
|
||||||
|
DefaultWikiBranch string
|
||||||
ExternalWikiURL string
|
ExternalWikiURL string
|
||||||
EnableIssues bool
|
EnableIssues bool
|
||||||
EnableExternalTracker bool
|
EnableExternalTracker bool
|
||||||
|
|
|
@ -173,6 +173,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.DefaultBranch = setting.Repository.DefaultBranch
|
repo.DefaultBranch = setting.Repository.DefaultBranch
|
||||||
|
repo.DefaultWikiBranch = setting.Repository.DefaultBranch
|
||||||
|
|
||||||
if len(opts.DefaultBranch) > 0 {
|
if len(opts.DefaultBranch) > 0 {
|
||||||
repo.DefaultBranch = opts.DefaultBranch
|
repo.DefaultBranch = opts.DefaultBranch
|
||||||
|
@ -240,6 +241,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
|
||||||
TrustModel: opts.TrustModel,
|
TrustModel: opts.TrustModel,
|
||||||
IsMirror: opts.IsMirror,
|
IsMirror: opts.IsMirror,
|
||||||
DefaultBranch: opts.DefaultBranch,
|
DefaultBranch: opts.DefaultBranch,
|
||||||
|
DefaultWikiBranch: setting.Repository.DefaultBranch,
|
||||||
ObjectFormatName: opts.ObjectFormatName,
|
ObjectFormatName: opts.ObjectFormatName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,54 @@ import (
|
||||||
"code.gitea.io/gitea/modules/util"
|
"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
|
// MigrateRepositoryGitData starts migrating git related data after created migrating repository
|
||||||
func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
|
func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
|
||||||
repo *repo_model.Repository, opts migration.MigrateOptions,
|
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
|
migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second
|
||||||
|
|
||||||
var err error
|
if err := util.RemoveAll(repoPath); err != nil {
|
||||||
if err = util.RemoveAll(repoPath); err != nil {
|
return repo, fmt.Errorf("failed to remove existing repo dir %q, err: %w", repoPath, err)
|
||||||
return repo, fmt.Errorf("Failed to remove %s: %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,
|
Mirror: true,
|
||||||
Quiet: true,
|
Quiet: true,
|
||||||
Timeout: migrateTimeout,
|
Timeout: migrateTimeout,
|
||||||
SkipTLSVerify: setting.Migrations.SkipTLSVerify,
|
SkipTLSVerify: setting.Migrations.SkipTLSVerify,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
if errors.Is(err, context.DeadlineExceeded) {
|
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 {
|
if err := git.WriteCommitGraph(ctx, repoPath); err != nil {
|
||||||
|
@ -66,37 +113,18 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Wiki {
|
if opts.Wiki {
|
||||||
wikiPath := repo_model.WikiPath(u.Name, opts.RepoName)
|
defaultWikiBranch, err := cloneWiki(ctx, u, opts, migrateTimeout)
|
||||||
wikiRemotePath := repo_module.WikiRemoteURL(ctx, opts.CloneAddr)
|
if err != nil {
|
||||||
if len(wikiRemotePath) > 0 {
|
return repo, fmt.Errorf("clone wiki error: %w", err)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
repo.DefaultWikiBranch = defaultWikiBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.OwnerID == u.ID {
|
if repo.OwnerID == u.ID {
|
||||||
repo.Owner = u
|
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)
|
return repo, fmt.Errorf("checkDaemonExportOK: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,18 +6,22 @@ package wiki
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
system_model "code.gitea.io/gitea/models/system"
|
system_model "code.gitea.io/gitea/models/system"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/sync"
|
"code.gitea.io/gitea/modules/sync"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
)
|
)
|
||||||
|
@ -25,10 +29,7 @@ import (
|
||||||
// TODO: use clustered lock (unique queue? or *abuse* cache)
|
// TODO: use clustered lock (unique queue? or *abuse* cache)
|
||||||
var wikiWorkingPool = sync.NewExclusivePool()
|
var wikiWorkingPool = sync.NewExclusivePool()
|
||||||
|
|
||||||
const (
|
const DefaultRemote = "origin"
|
||||||
DefaultRemote = "origin"
|
|
||||||
DefaultBranch = "master"
|
|
||||||
)
|
|
||||||
|
|
||||||
// InitWiki initializes a wiki for repository,
|
// InitWiki initializes a wiki for repository,
|
||||||
// it does nothing when repository already has wiki.
|
// 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)
|
return fmt.Errorf("InitRepository: %w", err)
|
||||||
} else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
|
} else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
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 {
|
} 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 master: %w", err)
|
return fmt.Errorf("unable to set default wiki branch to %q: %w", repo.DefaultWikiBranch, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepareGitPath try to find a suitable file path with file name by the given raw wiki name.
|
// 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
|
// 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"
|
unescaped := string(wikiPath) + ".md"
|
||||||
gitPath := WebPathToGitPath(wikiPath)
|
gitPath := WebPathToGitPath(wikiPath)
|
||||||
|
|
||||||
// Look for both files
|
// Look for both files
|
||||||
filesInIndex, err := gitRepo.LsTree(DefaultBranch, unescaped, gitPath)
|
filesInIndex, err := gitRepo.LsTree(defaultWikiBranch, unescaped, gitPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "Not a valid object name master") {
|
if strings.Contains(err.Error(), "Not a valid object name") {
|
||||||
return false, gitPath, nil
|
return false, gitPath, nil // branch doesn't exist
|
||||||
}
|
}
|
||||||
log.Error("%v", err)
|
log.Error("Wiki LsTree failed, err: %v", err)
|
||||||
return false, gitPath, 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)
|
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")
|
basePath, err := repo_module.CreateTemporaryPath("update-wiki")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -112,8 +113,8 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||||
Shared: true,
|
Shared: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasMasterBranch {
|
if hasDefaultBranch {
|
||||||
cloneOpts.Branch = DefaultBranch
|
cloneOpts.Branch = repo.DefaultWikiBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := git.Clone(ctx, repo.WikiPath(), basePath, cloneOpts); err != nil {
|
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()
|
defer gitRepo.Close()
|
||||||
|
|
||||||
if hasMasterBranch {
|
if hasDefaultBranch {
|
||||||
if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
|
if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
|
||||||
log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
|
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)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -151,7 +152,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||||
isOldWikiExist := true
|
isOldWikiExist := true
|
||||||
oldWikiPath := newWikiPath
|
oldWikiPath := newWikiPath
|
||||||
if oldWikiName != newWikiName {
|
if oldWikiName != newWikiName {
|
||||||
isOldWikiExist, oldWikiPath, err = prepareGitPath(gitRepo, oldWikiName)
|
isOldWikiExist, oldWikiPath, err = prepareGitPath(gitRepo, repo.DefaultWikiBranch, oldWikiName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -200,7 +201,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||||
} else {
|
} else {
|
||||||
commitTreeOpts.NoGPGSign = true
|
commitTreeOpts.NoGPGSign = true
|
||||||
}
|
}
|
||||||
if hasMasterBranch {
|
if hasDefaultBranch {
|
||||||
commitTreeOpts.Parents = []string{"HEAD"}
|
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{
|
if err := git.Push(gitRepo.Ctx, basePath, git.PushOptions{
|
||||||
Remote: DefaultRemote,
|
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(
|
Env: repo_module.FullPushingEnvironment(
|
||||||
doer,
|
doer,
|
||||||
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{
|
if err := git.Clone(ctx, repo.WikiPath(), basePath, git.CloneRepoOptions{
|
||||||
Bare: true,
|
Bare: true,
|
||||||
Shared: true,
|
Shared: true,
|
||||||
Branch: DefaultBranch,
|
Branch: repo.DefaultWikiBranch,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
|
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
|
||||||
return fmt.Errorf("failed to clone repository: %s (%w)", 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)
|
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 {
|
if err != nil {
|
||||||
return err
|
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{
|
if err := git.Push(gitRepo.Ctx, basePath, git.PushOptions{
|
||||||
Remote: DefaultRemote,
|
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(
|
Env: repo_module.FullPushingEnvironment(
|
||||||
doer,
|
doer,
|
||||||
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())
|
system_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath())
|
||||||
return nil
|
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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
masterTree, err := gitRepo.GetTree(DefaultBranch)
|
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
gitPath := WebPathToGitPath(webPath)
|
gitPath := WebPathToGitPath(webPath)
|
||||||
entry, err := masterTree.GetTreeEntryByPath(gitPath)
|
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:
|
// Now need to show that the page has been added:
|
||||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
masterTree, err := gitRepo.GetTree(DefaultBranch)
|
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
gitPath := WebPathToGitPath(webPath)
|
gitPath := WebPathToGitPath(webPath)
|
||||||
entry, err := masterTree.GetTreeEntryByPath(gitPath)
|
entry, err := masterTree.GetTreeEntryByPath(gitPath)
|
||||||
|
@ -242,7 +242,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
masterTree, err := gitRepo.GetTree(DefaultBranch)
|
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
gitPath := WebPathToGitPath("Home")
|
gitPath := WebPathToGitPath("Home")
|
||||||
_, err = masterTree.GetTreeEntryByPath(gitPath)
|
_, err = masterTree.GetTreeEntryByPath(gitPath)
|
||||||
|
@ -280,7 +280,7 @@ func TestPrepareWikiFileName(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
webPath := UserTitleToWebPath("", tt.arg)
|
webPath := UserTitleToWebPath("", tt.arg)
|
||||||
existence, newWikiPath, err := prepareGitPath(gitRepo, webPath)
|
existence, newWikiPath, err := prepareGitPath(gitRepo, repo.DefaultWikiBranch, webPath)
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
return
|
return
|
||||||
|
@ -312,7 +312,7 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
|
|
||||||
existence, newWikiPath, err := prepareGitPath(gitRepo, "Home")
|
existence, newWikiPath, err := prepareGitPath(gitRepo, "master", "Home")
|
||||||
assert.False(t, existence)
|
assert.False(t, existence)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, "Home.md", newWikiPath)
|
assert.EqualValues(t, "Home.md", newWikiPath)
|
||||||
|
|
|
@ -335,6 +335,10 @@
|
||||||
<label>{{ctx.Locale.Tr "repo.settings.use_internal_wiki"}}</label>
|
<label>{{ctx.Locale.Tr "repo.settings.use_internal_wiki"}}</label>
|
||||||
</div>
|
</div>
|
||||||
</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="field">
|
||||||
<div class="ui radio checkbox{{if $isExternalWikiGlobalDisabled}} disabled{{end}}"{{if $isExternalWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
|
<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}}>
|
<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}}>
|
||||||
|
|
|
@ -36,9 +36,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="text right">
|
<div class="text right">
|
||||||
<button class="ui primary button">
|
<a class="ui basic cancel button" href="{{.Link}}">{{ctx.Locale.Tr "cancel"}}</a>
|
||||||
{{ctx.Locale.Tr "repo.wiki.save_page"}}
|
<button class="ui primary button">{{ctx.Locale.Tr "repo.wiki.save_page"}}</button>
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
|
{{if .IsRepositoryAdmin}}<div>{{ctx.Locale.Tr "repo.default_branch"}}: {{.Repository.DefaultWikiBranch}}</div>{{end}}
|
||||||
<table class="ui table wiki-pages-list">
|
<table class="ui table wiki-pages-list">
|
||||||
<tbody>
|
<tbody>
|
||||||
{{range .Pages}}
|
{{range .Pages}}
|
||||||
|
|
Loading…
Reference in a new issue