fix modules/wikies/wiki.go /api/v1/repo/wiki.go

This commit is contained in:
wonderful 2021-08-09 14:38:48 +08:00
parent d9495f6822
commit 23f2dc9c23
3 changed files with 400 additions and 49 deletions

View File

@ -7,11 +7,19 @@
package wikies
import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/util"
"fmt"
"os"
//"github.com/unknwon/com"
"io/ioutil"
"net/url"
"strings"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
wiki_service "code.gitea.io/gitea/services/wiki"
)
@ -72,3 +80,235 @@ func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) []byte {
}
return content
}
func CreateWikiPage(doer *models.User, repo *models.Repository, wikiName, content, message string) error {
return updateWikiPage(doer, repo, "", wikiName, content, message, true)
}
func EditWikiPage(doer *models.User, repo *models.Repository, oldWikiName,newWikiName, content, message string) error {
return updateWikiPage(doer, repo, oldWikiName , newWikiName, content, message, false)
}
func updateWikiPage(doer *models.User, repo *models.Repository, oldWikiName, newWikiName, content, message string, isNew bool) (err error) {
//if err = nameAllowed(newWikiName); err != nil {
// return err
//}
//wikiWorkingPool.CheckIn(com.ToStr(repo.ID))
//defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID))
//
//if err = InitWiki(repo); err != nil {
// return fmt.Errorf("InitWiki: %v", err)
//}
hasMasterBranch := git.IsBranchExist(repo.WikiPath(), "master")
basePath, err := models.CreateTemporaryPath("update-wiki")
if err != nil {
return err
}
defer func() {
if err := models.RemoveTemporaryPath(basePath); err != nil {
log.Error("Merge: RemoveTemporaryPath: %s", err)
}
}()
cloneOpts := git.CloneRepoOptions{
Bare: true,
Shared: true,
}
if hasMasterBranch {
cloneOpts.Branch = "master"
}
if err := git.Clone(repo.WikiPath(), basePath, cloneOpts); err != nil {
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err)
}
gitRepo, err := git.OpenRepository(basePath)
if err != nil {
log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
}
defer gitRepo.Close()
if hasMasterBranch {
if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
return fmt.Errorf("Unable to read HEAD tree to index in: %s %v", basePath, err)
}
}
newWikiPath := wiki_service.NameToFilename(newWikiName)
if isNew {
filesInIndex, err := gitRepo.LsFiles(newWikiPath)
if err != nil {
log.Error("%v", err)
return err
}
if util.IsStringInSlice(newWikiPath, filesInIndex) {
return models.ErrWikiAlreadyExist{
Title: newWikiPath,
}
}
} else {
oldWikiPath := wiki_service.NameToFilename(oldWikiName)
filesInIndex, err := gitRepo.LsFiles(oldWikiPath)
if err != nil {
log.Error("%v", err)
return err
}
if util.IsStringInSlice(oldWikiPath, filesInIndex) {
err := gitRepo.RemoveFilesFromIndex(oldWikiPath)
if err != nil {
log.Error("%v", err)
return err
}
}
}
// FIXME: The wiki doesn't have lfs support at present - if this changes need to check attributes here
objectHash, err := gitRepo.HashObject(strings.NewReader(content))
if err != nil {
log.Error("%v", err)
return err
}
if err := gitRepo.AddObjectToIndex("100644", objectHash, newWikiPath); err != nil {
log.Error("%v", err)
return err
}
tree, err := gitRepo.WriteTree()
if err != nil {
log.Error("%v", err)
return err
}
commitTreeOpts := git.CommitTreeOpts{
Message: message,
}
sign, signingKey, _ := repo.SignWikiCommit(doer)
if sign {
commitTreeOpts.KeyID = signingKey
} else {
commitTreeOpts.NoGPGSign = true
}
if hasMasterBranch {
commitTreeOpts.Parents = []string{"HEAD"}
}
commitHash, err := gitRepo.CommitTree(doer.NewGitSig(), tree, commitTreeOpts)
if err != nil {
log.Error("%v", err)
return err
}
if err := git.Push(basePath, git.PushOptions{
Remote: "origin",
Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
Env: models.FullPushingEnvironment(
doer,
doer,
repo,
repo.Name+".wiki",
0,
),
}); err != nil {
log.Error("%v", err)
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
return err
}
return fmt.Errorf("Push: %v", err)
}
return nil
}
func DeleteWikiPage(doer *models.User, repo *models.Repository, pageName string) (err error) {
basePath, err := models.CreateTemporaryPath("update-wiki")
if err != nil {
return err
}
if err := git.Clone(repo.WikiPath(), basePath, git.CloneRepoOptions{
Bare: true,
Shared: true,
Branch: "master",
}); err != nil {
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err)
}
gitRepo, err := git.OpenRepository(basePath)
if err != nil {
log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
}
defer gitRepo.Close()
if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
return fmt.Errorf("Unable to read HEAD tree to index in: %s %v", basePath, err)
}
wikiPath := wiki_service.NameToFilename(pageName)
filesInIndex, err := gitRepo.LsFiles(wikiPath)
found := false
for _, file := range filesInIndex {
if file == wikiPath {
found = true
break
}
}
if found {
err := gitRepo.RemoveFilesFromIndex(wikiPath)
if err != nil {
return err
}
} else {
return os.ErrNotExist
}
// FIXME: The wiki doesn't have lfs support at present - if this changes need to check attributes here
tree, err := gitRepo.WriteTree()
if err != nil {
return err
}
message := "Delete page '" + pageName + "'"
commitTreeOpts := git.CommitTreeOpts{
Message: message,
Parents: []string{"HEAD"},
}
sign, signingKey, _ := repo.SignWikiCommit(doer)
if sign {
commitTreeOpts.KeyID = signingKey
} else {
commitTreeOpts.NoGPGSign = true
}
commitHash, err := gitRepo.CommitTree(doer.NewGitSig(), tree, commitTreeOpts)
if err != nil {
return err
}
if err := git.Push(basePath, git.PushOptions{
Remote: "origin",
Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
Env: models.PushingEnvironment(doer, repo),
}); err != nil {
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
return err
}
return fmt.Errorf("Push: %v", err)
}
return nil
}

View File

@ -4,10 +4,12 @@ package repo
import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/markdown"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/wikies"
wiki_service "code.gitea.io/gitea/services/wiki"
"fmt"
"net/http"
)
@ -35,7 +37,9 @@ func WikiList(ctx *context.APIContext) {
wikiRepo, commit, err := wikies.FindWikiRepoCommit(ctx)
if err != nil {
ctx.JSON(http.StatusOK, []api.WikiesResponse{})
if wikiRepo != nil {
wikiRepo.Close()
}
return
}
@ -45,7 +49,7 @@ func WikiList(ctx *context.APIContext) {
wikiRepo.Close()
}
ctx.JSON(http.StatusOK, []api.WikiesResponse{})
//ctx.JSON(http.StatusOK, []api.WikiesResponse{})
return
}
@ -125,6 +129,9 @@ func GetWiki(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/Wiki"
wikiRepo, commit, _ := wikies.FindWikiRepoCommit(ctx)
pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
@ -175,8 +182,8 @@ func GetWiki(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, wiki)
}
func CreateWiki(ctx *context.APIContext) {
// swagger:operation POST /repos/{owner}/{repo}/wikis repository repoCreateWiki
func CreateWiki(ctx *context.APIContext, form api.WikiOption) {
// swagger:operation POST /repos/{owner}/{repo}/wikies repository repoCreateWiki
// ---
// summary: Create a wiki in a repository
// produces:
@ -197,12 +204,58 @@ func CreateWiki(ctx *context.APIContext) {
// schema:
// "$ref": "#/definitions/WikiOption"
// responses:
// "201":
// "200":
// "$ref": "#/responses/Wiki"
err2 := wikies.CreateWikiPage(ctx.User, ctx.Repo.Repository, form.Name, form.Content, form.CommitMessage)
if err2 != nil{
ctx.ServerError("CreateWikiPage", err2)
}
wikiRepo, commit, _ := wikies.FindWikiRepoCommit(ctx)
data, entry, pageFilename, _:= wikies.WikiContentsByName(ctx, commit, form.Name)
metas := ctx.Repo.Repository.ComposeDocumentMetas()
PageContent := markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
c, err := wikiRepo.GetCommitByPath(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
return
}
}
fmt.Println(form)
wiki := api.WikiResponse{
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,
Content: PageContent,
}
ctx.JSON(http.StatusOK, wiki)
}
func EditWiki(ctx *context.Context) {
func EditWiki(ctx *context.APIContext, form api.WikiOption) {
// swagger:operation PATCH /repos/{owner}/{repo}/wikies/{pagename} repository repoEditWiki
// ---
// summary: Edit a wiki in a repository
@ -231,10 +284,61 @@ func EditWiki(ctx *context.Context) {
// responses:
// "200":
// "$ref": "#/responses/Wiki"
fmt.Println(form)
//OldPageName := ctx.Params(":page")
oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
newWikiName := wiki_service.NormalizeWikiName(form.Name)
err2 := wikies.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName,newWikiName, form.Content, form.CommitMessage)
if err2 != nil{
ctx.ServerError("EditWikiPage", err2)
}
wikiRepo, commit, _ := wikies.FindWikiRepoCommit(ctx)
data, entry, pageFilename, _:= wikies.WikiContentsByName(ctx, commit, form.Name) //
metas := ctx.Repo.Repository.ComposeDocumentMetas()
PageContent := markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
c, err := wikiRepo.GetCommitByPath(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
return
}
}
fmt.Println(form)
wiki := api.WikiResponse{
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,
Content: PageContent,
}
ctx.JSON(http.StatusOK, wiki)
}
func DeleteWiki(ctx *context.Context) {
func DeleteWiki(ctx *context.APIContext) {
// swagger:operation DELETE /repos/{owner}/{repo}/wikies/{pagename} repository repoDeleteWiki
// ---
// summary: Delete a wiki in a repository
@ -259,6 +363,15 @@ func DeleteWiki(ctx *context.Context) {
// responses:
// "204":
// "$ref": "#/responses/empty"
// "404":
// "500":
// "$ref": "#/responses/notFound"
WikiPageName := ctx.Params(":page")
err := wikies.DeleteWikiPage(ctx.User, ctx.Repo.Repository, WikiPageName)
if err != nil{
ctx.Error(http.StatusInternalServerError,"DeleteWikiPage", err)
return
}
log.Trace("WikiPage deleted : %s%s", ctx.Repo.Repository.Name, WikiPageName)
ctx.Status(http.StatusNoContent)
}

View File

@ -8931,6 +8931,44 @@
"$ref": "#/responses/WikiList"
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Create a wiki in a repository",
"operationId": "repoCreateWiki",
"parameters": [
{
"type": "string",
"description": "owner of the repo",
"name": "owner",
"in": "path",
"required": true
},
{
"type": "string",
"description": "name of the repo",
"name": "repo",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/WikiOption"
}
}
],
"responses": {
"201": {
"$ref": "#/responses/Wiki"
}
}
}
},
"/repos/{owner}/{repo}/wikies/{pagename}": {
@ -9059,46 +9097,6 @@
}
}
},
"/repos/{owner}/{repo}/wikis": {
"post": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Create a wiki in a repository",
"operationId": "repoCreateWiki",
"parameters": [
{
"type": "string",
"description": "owner of the repo",
"name": "owner",
"in": "path",
"required": true
},
{
"type": "string",
"description": "name of the repo",
"name": "repo",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/WikiOption"
}
}
],
"responses": {
"201": {
"$ref": "#/responses/Wiki"
}
}
}
},
"/repositories/{id}": {
"get": {
"produces": [
@ -16373,4 +16371,4 @@
"TOTPHeader": []
}
]
}
}