初始提交: Gitea 项目代码
This commit is contained in:
@@ -0,0 +1,754 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/models/renderhelper"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unit"
|
||||
"gitea.dev/modules/base"
|
||||
"gitea.dev/modules/charset"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/gitrepo"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/markup"
|
||||
"gitea.dev/modules/markup/markdown"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/templates"
|
||||
"gitea.dev/modules/timeutil"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/modules/web"
|
||||
"gitea.dev/routers/common"
|
||||
"gitea.dev/services/context"
|
||||
"gitea.dev/services/forms"
|
||||
git_service "gitea.dev/services/git"
|
||||
notify_service "gitea.dev/services/notify"
|
||||
repo_service "gitea.dev/services/repository"
|
||||
wiki_service "gitea.dev/services/wiki"
|
||||
)
|
||||
|
||||
const (
|
||||
tplWikiStart templates.TplName = "repo/wiki/start"
|
||||
tplWikiView templates.TplName = "repo/wiki/view"
|
||||
tplWikiRevision templates.TplName = "repo/wiki/revision"
|
||||
tplWikiNew templates.TplName = "repo/wiki/new"
|
||||
tplWikiPages templates.TplName = "repo/wiki/pages"
|
||||
)
|
||||
|
||||
// MustEnableWiki check if wiki is enabled, if external then redirect
|
||||
func MustEnableWiki(ctx *context.Context) {
|
||||
if !ctx.Repo.Permission.CanRead(unit.TypeWiki) &&
|
||||
!ctx.Repo.Permission.CanRead(unit.TypeExternalWiki) {
|
||||
if log.IsTrace() {
|
||||
log.Trace("Permission Denied: User %-v cannot read %-v or %-v of repo %-v\n"+
|
||||
"User in repo has Permissions: %-+v",
|
||||
ctx.Doer,
|
||||
unit.TypeWiki,
|
||||
unit.TypeExternalWiki,
|
||||
ctx.Repo.Repository,
|
||||
ctx.Repo.Permission)
|
||||
}
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
|
||||
repoUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalWiki)
|
||||
if err == nil {
|
||||
ctx.Redirect(repoUnit.ExternalWikiConfig().ExternalWikiURL)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// PageMeta wiki page meta information
|
||||
type PageMeta struct {
|
||||
Name string
|
||||
SubURL string
|
||||
GitEntryName string
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
// findEntryForFile finds the tree entry for a target filepath.
|
||||
func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) {
|
||||
entry, err := commit.GetTreeEntryByPath(target)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
if entry != nil {
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// Then the unescaped, the shortest alternative
|
||||
var unescapedTarget string
|
||||
if unescapedTarget, err = url.QueryUnescape(target); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return commit.GetTreeEntryByPath(unescapedTarget)
|
||||
}
|
||||
|
||||
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
|
||||
wikiGitRepo, errGitRepo := gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||
if errGitRepo != nil {
|
||||
ctx.ServerError("OpenRepository", errGitRepo)
|
||||
return nil, nil, errGitRepo
|
||||
}
|
||||
|
||||
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 := gitrepo.GetDefaultBranch(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||
if errBranch != nil {
|
||||
return wikiGitRepo, nil, errBranch
|
||||
}
|
||||
// update the default branch in the database
|
||||
errDb := repo_model.UpdateRepositoryColsNoAutoTime(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)
|
||||
}
|
||||
if errCommit != nil {
|
||||
return wikiGitRepo, nil, errCommit
|
||||
}
|
||||
return wikiGitRepo, commit, nil
|
||||
}
|
||||
|
||||
// wikiContentsByEntry returns the contents of the wiki page referenced by the
|
||||
// given tree entry. Writes to ctx if an error occurs.
|
||||
func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
|
||||
reader, err := entry.Blob().DataAsync()
|
||||
if err != nil {
|
||||
ctx.ServerError("Blob.Data", err)
|
||||
return nil
|
||||
}
|
||||
defer reader.Close()
|
||||
content, err := util.ReadWithLimit(reader, 5*1024*1024) // 5MB should be enough for a wiki page
|
||||
if err != nil {
|
||||
ctx.ServerError("ReadAll", err)
|
||||
return nil
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
// wikiEntryByName returns the entry of a wiki page, along with a boolean
|
||||
// indicating whether the entry exists. Writes to ctx if an error occurs.
|
||||
// The last return value indicates whether the file should be returned as a raw file
|
||||
func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) {
|
||||
isRaw := false
|
||||
gitFilename := wiki_service.WebPathToGitPath(wikiName)
|
||||
entry, err := findEntryForFile(commit, gitFilename)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, "", false, false
|
||||
}
|
||||
if entry == nil {
|
||||
// check if the file without ".md" suffix exists
|
||||
gitFilename := strings.TrimSuffix(gitFilename, ".md")
|
||||
entry, err = findEntryForFile(commit, gitFilename)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, "", false, false
|
||||
}
|
||||
isRaw = true
|
||||
}
|
||||
if entry == nil {
|
||||
return nil, "", true, false
|
||||
}
|
||||
return entry, gitFilename, false, isRaw
|
||||
}
|
||||
|
||||
// wikiContentsByName returns the contents of a wiki page, along with a boolean
|
||||
// indicating whether the page exists. Writes to ctx if an error occurs.
|
||||
func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) {
|
||||
entry, gitFilename, noEntry, _ := wikiEntryByName(ctx, commit, wikiName)
|
||||
if entry == nil {
|
||||
return nil, nil, "", true
|
||||
}
|
||||
return wikiContentsByEntry(ctx, entry), entry, gitFilename, noEntry
|
||||
}
|
||||
|
||||
func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
|
||||
if err != nil {
|
||||
if !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// get the wiki pages list.
|
||||
entries, err := commit.ListEntries()
|
||||
if err != nil {
|
||||
ctx.ServerError("ListEntries", err)
|
||||
return nil, nil
|
||||
}
|
||||
pages := make([]PageMeta, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if !entry.IsRegular() {
|
||||
continue
|
||||
}
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entry.Name())
|
||||
if err != nil {
|
||||
if repo_model.IsErrWikiInvalidFileName(err) {
|
||||
continue
|
||||
}
|
||||
ctx.ServerError("WikiFilenameToName", err)
|
||||
return nil, nil
|
||||
} else if wikiName == "_Sidebar" || wikiName == "_Footer" {
|
||||
continue
|
||||
}
|
||||
_, displayName := wiki_service.WebPathToUserTitle(wikiName)
|
||||
pages = append(pages, PageMeta{
|
||||
Name: displayName,
|
||||
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
||||
GitEntryName: entry.Name(),
|
||||
})
|
||||
}
|
||||
ctx.Data["Pages"] = pages
|
||||
|
||||
// get requested page name
|
||||
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
||||
if len(pageName) == 0 {
|
||||
pageName = "Home"
|
||||
}
|
||||
|
||||
_, displayName := wiki_service.WebPathToUserTitle(pageName)
|
||||
ctx.Data["PageURL"] = wiki_service.WebPathToURLPath(pageName)
|
||||
ctx.Data["old_title"] = displayName
|
||||
ctx.Data["Title"] = displayName
|
||||
ctx.Data["title"] = displayName
|
||||
|
||||
isSideBar := pageName == "_Sidebar"
|
||||
isFooter := pageName == "_Footer"
|
||||
|
||||
// lookup filename in wiki - get gitTree entry , real filename
|
||||
entry, pageFilename, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName)
|
||||
if noEntry {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
|
||||
}
|
||||
if isRaw {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/raw/" + string(pageName))
|
||||
}
|
||||
if entry == nil || ctx.Written() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// get page content
|
||||
data := wikiContentsByEntry(ctx, entry)
|
||||
if ctx.Written() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rctx := renderhelper.NewRenderContextRepoWiki(ctx, ctx.Repo.Repository)
|
||||
|
||||
renderFn := func(data []byte) (escaped *charset.EscapeStatus, output template.HTML, err error) {
|
||||
buf := &strings.Builder{}
|
||||
markupRd, markupWr := io.Pipe()
|
||||
defer markupWr.Close()
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
escaped, _ = charset.EscapeControlReader(markupRd, buf, ctx.Locale, charset.EscapeOptionsForView())
|
||||
output = template.HTML(buf.String())
|
||||
buf.Reset()
|
||||
close(done)
|
||||
}()
|
||||
|
||||
err = markdown.Render(rctx, bytes.NewReader(data), markupWr)
|
||||
_ = markupWr.CloseWithError(err)
|
||||
<-done
|
||||
return escaped, output, err
|
||||
}
|
||||
|
||||
ctx.Data["EscapeStatus"], ctx.Data["WikiContentHTML"], err = renderFn(data)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if rctx.TocShowInSection == markup.TocShowInSidebar && len(rctx.TocHeadingItems) > 0 {
|
||||
sb := strings.Builder{}
|
||||
markup.RenderTocHeadingItems(rctx, map[string]string{"open": ""}, &sb)
|
||||
ctx.Data["WikiSidebarTocHTML"] = template.HTML(sb.String())
|
||||
}
|
||||
|
||||
if !isSideBar {
|
||||
sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
|
||||
if ctx.Written() {
|
||||
return nil, nil
|
||||
}
|
||||
ctx.Data["WikiSidebarEscapeStatus"], ctx.Data["WikiSidebarHTML"], err = renderFn(sidebarContent)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
if !isFooter {
|
||||
footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
|
||||
if ctx.Written() {
|
||||
return nil, nil
|
||||
}
|
||||
ctx.Data["WikiFooterEscapeStatus"], ctx.Data["WikiFooterHTML"], err = renderFn(footerContent)
|
||||
if err != nil {
|
||||
ctx.ServerError("Render", err)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// get commit count - wiki revisions
|
||||
commitsCount, _ := gitrepo.FileCommitsCount(ctx, ctx.Repo.Repository.WikiStorageRepo(), ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
|
||||
ctx.Data["CommitCount"] = commitsCount
|
||||
|
||||
return wikiGitRepo, entry
|
||||
}
|
||||
|
||||
func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
|
||||
if err != nil {
|
||||
if !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// get requested page name
|
||||
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
||||
if len(pageName) == 0 {
|
||||
pageName = "Home"
|
||||
}
|
||||
|
||||
_, displayName := wiki_service.WebPathToUserTitle(pageName)
|
||||
ctx.Data["PageURL"] = wiki_service.WebPathToURLPath(pageName)
|
||||
ctx.Data["old_title"] = displayName
|
||||
ctx.Data["Title"] = displayName
|
||||
ctx.Data["title"] = displayName
|
||||
|
||||
// lookup filename in wiki - get page content, gitTree entry , real filename
|
||||
_, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
|
||||
if noEntry {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
|
||||
}
|
||||
if entry == nil || ctx.Written() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// get commit count - wiki revisions
|
||||
commitsCount, _ := gitrepo.FileCommitsCount(ctx, ctx.Repo.Repository.WikiStorageRepo(), ctx.Repo.Repository.DefaultWikiBranch, pageFilename)
|
||||
ctx.Data["CommitCount"] = commitsCount
|
||||
|
||||
// get page
|
||||
page := max(ctx.FormInt("page"), 1)
|
||||
|
||||
// get Commit Count
|
||||
commitsHistory, err := wikiGitRepo.CommitsByFileAndRange(
|
||||
git.CommitsByFileAndRangeOptions{
|
||||
Revision: ctx.Repo.Repository.DefaultWikiBranch,
|
||||
File: pageFilename,
|
||||
Page: page,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("CommitsByFileAndRange", err)
|
||||
return nil, nil
|
||||
}
|
||||
ctx.Data["Commits"], err = git_service.ConvertFromGitCommit(ctx, commitsHistory, ctx.Repo.Repository)
|
||||
if err != nil {
|
||||
ctx.ServerError("ConvertFromGitCommit", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pager := context.NewPagination(commitsCount, setting.Git.CommitsRangeSize, page, 5)
|
||||
pager.AddParamFromRequest(ctx.Req)
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
return wikiGitRepo, entry
|
||||
}
|
||||
|
||||
func renderEditPage(ctx *context.Context) {
|
||||
_, commit, err := findWikiRepoCommit(ctx)
|
||||
if err != nil {
|
||||
if !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get requested page name
|
||||
pageName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
||||
if len(pageName) == 0 {
|
||||
pageName = "Home"
|
||||
}
|
||||
|
||||
_, displayName := wiki_service.WebPathToUserTitle(pageName)
|
||||
ctx.Data["PageURL"] = wiki_service.WebPathToURLPath(pageName)
|
||||
ctx.Data["old_title"] = displayName
|
||||
ctx.Data["Title"] = displayName
|
||||
ctx.Data["title"] = displayName
|
||||
|
||||
// lookup filename in wiki - gitTree entry , real filename
|
||||
entry, _, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName)
|
||||
if noEntry {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
|
||||
}
|
||||
if isRaw {
|
||||
ctx.HTTPError(http.StatusForbidden, "Editing of raw wiki files is not allowed")
|
||||
}
|
||||
if entry == nil || ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
// get wiki page content
|
||||
data := wikiContentsByEntry(ctx, entry)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["WikiEditContent"] = string(data)
|
||||
}
|
||||
|
||||
// WikiPost renders post of wiki page
|
||||
func WikiPost(ctx *context.Context) {
|
||||
switch ctx.FormString("action") {
|
||||
case "_new":
|
||||
if !ctx.Repo.Permission.CanWrite(unit.TypeWiki) {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
NewWikiPost(ctx)
|
||||
return
|
||||
case "_delete":
|
||||
if !ctx.Repo.Permission.CanWrite(unit.TypeWiki) {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
DeleteWikiPagePost(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Repo.Permission.CanWrite(unit.TypeWiki) {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
EditWikiPost(ctx)
|
||||
}
|
||||
|
||||
// Wiki renders single wiki page
|
||||
func Wiki(ctx *context.Context) {
|
||||
ctx.Data["CanWriteWiki"] = ctx.Repo.Permission.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
|
||||
|
||||
switch ctx.FormString("action") {
|
||||
case "_pages":
|
||||
WikiPages(ctx)
|
||||
return
|
||||
case "_revision":
|
||||
WikiRevision(ctx)
|
||||
return
|
||||
case "_edit":
|
||||
if !ctx.Repo.Permission.CanWrite(unit.TypeWiki) {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
EditWiki(ctx)
|
||||
return
|
||||
case "_new":
|
||||
if !ctx.Repo.Permission.CanWrite(unit.TypeWiki) {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
NewWiki(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
if !repo_service.HasWiki(ctx, ctx.Repo.Repository) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki")
|
||||
ctx.HTML(http.StatusOK, tplWikiStart)
|
||||
return
|
||||
}
|
||||
|
||||
wikiGitRepo, entry := renderViewPage(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
if entry == nil {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki")
|
||||
ctx.HTML(http.StatusOK, tplWikiStart)
|
||||
return
|
||||
}
|
||||
|
||||
wikiPath := entry.Name()
|
||||
detectedRender := markup.DetectRendererTypeByFilename(wikiPath)
|
||||
if detectedRender == nil || detectedRender.Name() != markdown.MarkupName {
|
||||
ctx.Data["FormatWarning"] = "File extension " + path.Ext(wikiPath) + " is not supported at the moment. Rendered as Markdown."
|
||||
}
|
||||
// Get last change information.
|
||||
lastCommit, err := wikiGitRepo.GetCommitByPath(wikiPath)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetCommitByPath", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Author"] = lastCommit.Author
|
||||
|
||||
ctx.HTML(http.StatusOK, tplWikiView)
|
||||
}
|
||||
|
||||
// WikiRevision renders file revision list of wiki page
|
||||
func WikiRevision(ctx *context.Context) {
|
||||
ctx.Data["CanWriteWiki"] = ctx.Repo.Permission.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
|
||||
|
||||
if !repo_service.HasWiki(ctx, ctx.Repo.Repository) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki")
|
||||
ctx.HTML(http.StatusOK, tplWikiStart)
|
||||
return
|
||||
}
|
||||
|
||||
wikiGitRepo, entry := renderRevisionPage(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
if entry == nil {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki")
|
||||
ctx.HTML(http.StatusOK, tplWikiStart)
|
||||
return
|
||||
}
|
||||
|
||||
// Get last change information.
|
||||
wikiPath := entry.Name()
|
||||
lastCommit, err := wikiGitRepo.GetCommitByPath(wikiPath)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetCommitByPath", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Author"] = lastCommit.Author
|
||||
|
||||
ctx.HTML(http.StatusOK, tplWikiRevision)
|
||||
}
|
||||
|
||||
// WikiPages render wiki pages list page
|
||||
func WikiPages(ctx *context.Context) {
|
||||
if !repo_service.HasWiki(ctx, ctx.Repo.Repository) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki.pages")
|
||||
ctx.Data["CanWriteWiki"] = ctx.Repo.Permission.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
|
||||
|
||||
_, commit, err := findWikiRepoCommit(ctx)
|
||||
if err != nil {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
|
||||
return
|
||||
}
|
||||
|
||||
treePath := "" // To support list sub folders' pages in the future
|
||||
tree, err := commit.SubTree(treePath)
|
||||
if err != nil {
|
||||
ctx.ServerError("SubTree", err)
|
||||
return
|
||||
}
|
||||
|
||||
allEntries, err := tree.ListEntries()
|
||||
if err != nil {
|
||||
ctx.ServerError("ListEntries", err)
|
||||
return
|
||||
}
|
||||
allEntries.CustomSort(base.NaturalSortCompare)
|
||||
|
||||
entries, _, err := allEntries.GetCommitsInfo(ctx, ctx.Repo.RepoLink, commit, treePath)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetCommitsInfo", err)
|
||||
return
|
||||
}
|
||||
|
||||
pages := make([]PageMeta, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if !entry.Entry.IsRegular() {
|
||||
continue
|
||||
}
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entry.Entry.Name())
|
||||
if err != nil {
|
||||
if repo_model.IsErrWikiInvalidFileName(err) {
|
||||
continue
|
||||
}
|
||||
ctx.ServerError("WikiFilenameToName", err)
|
||||
return
|
||||
}
|
||||
_, displayName := wiki_service.WebPathToUserTitle(wikiName)
|
||||
pages = append(pages, PageMeta{
|
||||
Name: displayName,
|
||||
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
||||
GitEntryName: entry.Entry.Name(),
|
||||
UpdatedUnix: timeutil.TimeStamp(entry.Commit.Author.When.Unix()),
|
||||
})
|
||||
}
|
||||
ctx.Data["Pages"] = pages
|
||||
|
||||
ctx.HTML(http.StatusOK, tplWikiPages)
|
||||
}
|
||||
|
||||
// WikiRaw outputs raw blob requested by user (image for example)
|
||||
func WikiRaw(ctx *context.Context) {
|
||||
_, commit, err := findWikiRepoCommit(ctx)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
ctx.ServerError("findEntryForfile", err)
|
||||
return
|
||||
}
|
||||
|
||||
providedWebPath := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
||||
providedGitPath := wiki_service.WebPathToGitPath(providedWebPath)
|
||||
var entry *git.TreeEntry
|
||||
if commit != nil {
|
||||
// Try to find a file with that name
|
||||
entry, err = findEntryForFile(commit, providedGitPath)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
}
|
||||
|
||||
if entry == nil {
|
||||
// Try to find a wiki page with that name
|
||||
providedGitPath = strings.TrimSuffix(providedGitPath, ".md")
|
||||
entry, err = findEntryForFile(commit, providedGitPath)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if entry != nil {
|
||||
if err = common.ServeBlob(ctx.Base, ctx.Repo.Repository, ctx.Repo.TreePath, entry.Blob(), nil); err != nil {
|
||||
ctx.ServerError("ServeBlob", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.NotFound(nil)
|
||||
}
|
||||
|
||||
// NewWiki render wiki create page
|
||||
func NewWiki(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
|
||||
|
||||
if !repo_service.HasWiki(ctx, ctx.Repo.Repository) {
|
||||
ctx.Data["title"] = "Home"
|
||||
}
|
||||
if ctx.FormString("title") != "" {
|
||||
ctx.Data["title"] = ctx.FormString("title")
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, tplWikiNew)
|
||||
}
|
||||
|
||||
// NewWikiPost response for wiki create request
|
||||
func NewWikiPost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.NewWikiForm)
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(http.StatusOK, tplWikiNew)
|
||||
return
|
||||
}
|
||||
|
||||
if util.IsEmptyString(form.Title) {
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.issues.new.title_empty"), tplWikiNew, form)
|
||||
return
|
||||
}
|
||||
|
||||
wikiName := wiki_service.UserTitleToWebPath("", form.Title)
|
||||
|
||||
if len(form.Message) == 0 {
|
||||
form.Message = ctx.Locale.TrString("repo.editor.add", form.Title)
|
||||
}
|
||||
|
||||
if err := wiki_service.AddWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil {
|
||||
if repo_model.IsErrWikiReservedName(err) {
|
||||
ctx.Data["Err_Title"] = true
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.wiki.reserved_page", wikiName), tplWikiNew, &form)
|
||||
} else if repo_model.IsErrWikiAlreadyExist(err) {
|
||||
ctx.Data["Err_Title"] = true
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("repo.wiki.page_already_exists"), tplWikiNew, &form)
|
||||
} else {
|
||||
ctx.ServerError("AddWikiPage", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
notify_service.NewWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, string(wikiName), form.Message)
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.WebPathToURLPath(wikiName))
|
||||
}
|
||||
|
||||
// EditWiki render wiki modify page
|
||||
func EditWiki(ctx *context.Context) {
|
||||
ctx.Data["PageIsWikiEdit"] = true
|
||||
|
||||
if !repo_service.HasWiki(ctx, ctx.Repo.Repository) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
|
||||
return
|
||||
}
|
||||
|
||||
renderEditPage(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, tplWikiNew)
|
||||
}
|
||||
|
||||
// EditWikiPost response for wiki modify request
|
||||
func EditWikiPost(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.NewWikiForm)
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(http.StatusOK, tplWikiNew)
|
||||
return
|
||||
}
|
||||
|
||||
oldWikiName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
||||
newWikiName := wiki_service.UserTitleToWebPath("", form.Title)
|
||||
|
||||
if len(form.Message) == 0 {
|
||||
form.Message = ctx.Locale.TrString("repo.editor.update", form.Title)
|
||||
}
|
||||
|
||||
if err := wiki_service.EditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil {
|
||||
ctx.ServerError("EditWikiPage", err)
|
||||
return
|
||||
}
|
||||
|
||||
notify_service.EditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, string(newWikiName), form.Message)
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.WebPathToURLPath(newWikiName))
|
||||
}
|
||||
|
||||
// DeleteWikiPagePost delete wiki page
|
||||
func DeleteWikiPagePost(ctx *context.Context) {
|
||||
wikiName := wiki_service.WebPathFromRequest(ctx.PathParamRaw("*"))
|
||||
if len(wikiName) == 0 {
|
||||
wikiName = "Home"
|
||||
}
|
||||
|
||||
if err := wiki_service.DeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName); err != nil {
|
||||
ctx.ServerError("DeleteWikiPage", err)
|
||||
return
|
||||
}
|
||||
|
||||
notify_service.DeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, string(wikiName))
|
||||
|
||||
ctx.JSONRedirect(ctx.Repo.RepoLink + "/wiki/")
|
||||
}
|
||||
Reference in New Issue
Block a user