gitea-1156/routers/api/v1/repo/wiki.go

335 lines
8.0 KiB
Go

package repo
import (
"bytes"
"net/http"
"sort"
"strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
webWiki "code.gitea.io/gitea/routers/web/repo"
wiki_service "code.gitea.io/gitea/services/wiki"
)
func ListWikiPages(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/wikies repository repoWikiList
// ---
// summary: List the wikies in a repository
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/WikiList"
if !ctx.Repo.Repository.HasWiki() {
return
}
wikiCloneWiki := ctx.Repo.Repository.WikiCloneLink()
wikiRepo, commit, err := webWiki.FindWikiRepoCommit(ctx.Context)
if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
return
}
defer func() {
if wikiRepo != nil {
wikiRepo.Close()
}
}()
entries, err := commit.ListEntries()
if err != nil {
ctx.ServerError("entries", err)
return
}
pages := make([]api.WikiesResponse, 0, len(entries))
for _, entry := range entries {
if !entry.IsRegular() {
continue
}
lastCommit, firstCommit, _ := wikiRepo.GetFirstAndLastCommitByPath("master", entry.Name())
if err != nil {
ctx.ServerError("GetCommitByPath", err)
return
}
wikiName, err := wiki_service.FilenameToName(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
continue
}
ctx.ServerError("FilenameToName", err)
return
}
pages = append(pages, api.WikiesResponse{
WikiCloneLink: api.CloneLink{
HTTPS: wikiCloneWiki.HTTPS,
SSH: wikiCloneWiki.SSH,
},
WikiMeta: api.WikiMeta{
Name: wikiName,
Commit: api.WikiCommit{
Author: api.WikiUser{
Name: lastCommit.Author.Name,
Email: lastCommit.Author.Email,
When: lastCommit.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: lastCommit.Committer.Name,
Email: lastCommit.Committer.Email,
When: lastCommit.Author.When.Unix(),
},
ID: lastCommit.ID.String(),
Message: lastCommit.Message(),
},
FirstCommit: api.WikiCommit{
Author: api.WikiUser{
Name: firstCommit.Author.Name,
Email: firstCommit.Author.Email,
When: firstCommit.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: firstCommit.Committer.Name,
Email: firstCommit.Committer.Email,
When: firstCommit.Author.When.Unix(),
},
ID: firstCommit.ID.String(),
Message: firstCommit.Message(),
},
},
})
}
//sort by time
sort.Slice(pages, func(i, j int) bool {
return pages[i].FirstCommit.Author.When > pages[j].FirstCommit.Author.When
})
ctx.JSON(http.StatusOK, pages)
}
func CreateWiki(ctx *context.APIContext) {
// swagger:operation POST /repos/{owner}/{repo}/wikies repository repoCreateWiki
// ---
// summary: Create a wiki in a repository
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/WikiOption"
// responses:
// "200":
// "$ref": "#/responses/Wiki"
form := web.GetForm(ctx).(*api.WikiOption)
err := wiki_service.CheckFile(form.Name)
if err != nil {
ctx.FileNameError()
return
}
wikiName := wiki_service.NormalizeWikiName(form.Name)
wikiCloneLink := ctx.Repo.Repository.WikiCloneLink()
if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.CommitMessage); err != nil {
if models.IsErrWikiReservedName(err) {
ctx.Error(http.StatusInternalServerError, "WikiNameIsReservedPage", "wiki名称是被保留的.")
} else if models.IsErrWikiAlreadyExist(err) {
ctx.Error(http.StatusConflict, "WikiNameAlreadyExist", "wiki名称已存在")
} else {
ctx.Error(http.StatusInternalServerError, "AddWikiPage", err)
}
return
}
wikiRepo, commit, _ := webWiki.FindWikiRepoCommit(ctx.Context)
data, entry, pageFilename, _ := webWiki.WikiContentsByName(ctx.Context, commit, form.Name)
metas := ctx.Repo.Repository.ComposeDocumentMetas()
var rctx = &markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: metas,
IsWiki: true,
}
var buf strings.Builder
if err := markdown.Render(rctx, bytes.NewReader(data), &buf); err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("Render", err)
return
}
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
c, err := wikiRepo.GetCommitByPath(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
return
}
}
wiki := api.WikiResponse{
WikiCloneLink: api.CloneLink{
HTTPS: wikiCloneLink.HTTPS,
SSH: wikiCloneLink.SSH,
},
WikiMeta: api.WikiMeta{
Name: form.Name,
Commit: api.WikiCommit{
Author: api.WikiUser{
Name: c.Author.Name,
Email: c.Author.Email,
When: c.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: c.Committer.Name,
Email: c.Committer.Email,
When: c.Author.When.Unix(),
},
ID: c.ID.String(),
Message: c.Message(),
},
},
CommitCounts: commitsCount,
MdContent: string(data),
SimpleContent: buf.String(),
}
ctx.JSON(http.StatusOK, wiki)
}
func GetWiki(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/wikies/{pagename} repository repoGetWiki
// ---
// summary: Get a Wiki
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: pagename
// in: path
// description: name of the wikipage
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/Wiki"
wikiRepo, commit, _ := webWiki.FindWikiRepoCommit(ctx.Context)
wikiCloneWiki := ctx.Repo.Repository.WikiCloneLink()
// pageName := wiki_service.NormalizeWikiName(ctx.Context.Params(":page"))
pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
if len(pageName) == 0 {
pageName = "Home"
}
data, entry, pageFilename, noEntry := webWiki.WikiContentsByName(ctx.Context, commit, pageName)
if noEntry {
ctx.NotFound()
return
}
if entry == nil || ctx.Written() {
if wikiRepo != nil {
wikiRepo.Close()
}
}
metas := ctx.Repo.Repository.ComposeDocumentMetas()
var rctx = &markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,
Metas: metas,
IsWiki: true,
}
var buf strings.Builder
if err := markdown.Render(rctx, bytes.NewReader(data), &buf); err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("Render", err)
return
}
c, err := wikiRepo.GetCommitByPath(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
return
}
}
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
wiki := api.WikiResponse{
WikiCloneLink: api.CloneLink{
HTTPS: wikiCloneWiki.HTTPS,
SSH: wikiCloneWiki.SSH,
},
WikiMeta: api.WikiMeta{
Name: pageName,
Commit: api.WikiCommit{
Author: api.WikiUser{
Name: c.Author.Name,
Email: c.Author.Email,
When: c.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: c.Committer.Name,
Email: c.Committer.Email,
When: c.Author.When.Unix(),
},
ID: c.ID.String(),
Message: c.Message(),
},
},
CommitCounts: commitsCount,
MdContent: string(data),
SimpleContent: buf.String(),
}
ctx.JSON(http.StatusOK, wiki)
}
func DeleteWiki(ctx *context.APIContext) {
}
func EditWiki(ctx *context.APIContext) {
}