You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wiki.go 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package repo
  6. import (
  7. "fmt"
  8. "io/ioutil"
  9. "net/url"
  10. "path/filepath"
  11. "strings"
  12. "code.gitea.io/gitea/models"
  13. "code.gitea.io/gitea/modules/auth"
  14. "code.gitea.io/gitea/modules/base"
  15. "code.gitea.io/gitea/modules/context"
  16. "code.gitea.io/gitea/modules/git"
  17. "code.gitea.io/gitea/modules/log"
  18. "code.gitea.io/gitea/modules/markup"
  19. "code.gitea.io/gitea/modules/markup/markdown"
  20. "code.gitea.io/gitea/modules/timeutil"
  21. "code.gitea.io/gitea/modules/util"
  22. )
  23. const (
  24. tplWikiStart base.TplName = "repo/wiki/start"
  25. tplWikiView base.TplName = "repo/wiki/view"
  26. tplWikiRevision base.TplName = "repo/wiki/revision"
  27. tplWikiNew base.TplName = "repo/wiki/new"
  28. tplWikiPages base.TplName = "repo/wiki/pages"
  29. )
  30. // MustEnableWiki check if wiki is enabled, if external then redirect
  31. func MustEnableWiki(ctx *context.Context) {
  32. if !ctx.Repo.CanRead(models.UnitTypeWiki) &&
  33. !ctx.Repo.CanRead(models.UnitTypeExternalWiki) {
  34. if log.IsTrace() {
  35. log.Trace("Permission Denied: User %-v cannot read %-v or %-v of repo %-v\n"+
  36. "User in repo has Permissions: %-+v",
  37. ctx.User,
  38. models.UnitTypeWiki,
  39. models.UnitTypeExternalWiki,
  40. ctx.Repo.Repository,
  41. ctx.Repo.Permission)
  42. }
  43. ctx.NotFound("MustEnableWiki", nil)
  44. return
  45. }
  46. unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalWiki)
  47. if err == nil {
  48. ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
  49. return
  50. }
  51. }
  52. // PageMeta wiki page meta information
  53. type PageMeta struct {
  54. Name string
  55. SubURL string
  56. UpdatedUnix timeutil.TimeStamp
  57. }
  58. // findEntryForFile finds the tree entry for a target filepath.
  59. func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) {
  60. entries, err := commit.ListEntries()
  61. if err != nil {
  62. return nil, err
  63. }
  64. // The longest name should be checked first
  65. for _, entry := range entries {
  66. if entry.IsRegular() && entry.Name() == target {
  67. return entry, nil
  68. }
  69. }
  70. // Then the unescaped, shortest alternative
  71. var unescapedTarget string
  72. if unescapedTarget, err = url.QueryUnescape(target); err != nil {
  73. return nil, err
  74. }
  75. for _, entry := range entries {
  76. if entry.IsRegular() && entry.Name() == unescapedTarget {
  77. return entry, nil
  78. }
  79. }
  80. return nil, nil
  81. }
  82. func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
  83. wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath())
  84. if err != nil {
  85. ctx.ServerError("OpenRepository", err)
  86. return nil, nil, err
  87. }
  88. commit, err := wikiRepo.GetBranchCommit("master")
  89. if err != nil {
  90. return wikiRepo, nil, err
  91. }
  92. return wikiRepo, commit, nil
  93. }
  94. // wikiContentsByEntry returns the contents of the wiki page referenced by the
  95. // given tree entry. Writes to ctx if an error occurs.
  96. func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
  97. reader, err := entry.Blob().DataAsync()
  98. if err != nil {
  99. ctx.ServerError("Blob.Data", err)
  100. return nil
  101. }
  102. defer reader.Close()
  103. content, err := ioutil.ReadAll(reader)
  104. if err != nil {
  105. ctx.ServerError("ReadAll", err)
  106. return nil
  107. }
  108. return content
  109. }
  110. // wikiContentsByName returns the contents of a wiki page, along with a boolean
  111. // indicating whether the page exists. Writes to ctx if an error occurs.
  112. func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) {
  113. var entry *git.TreeEntry
  114. var err error
  115. pageFilename := models.WikiNameToFilename(wikiName)
  116. if entry, err = findEntryForFile(commit, pageFilename); err != nil {
  117. ctx.ServerError("findEntryForFile", err)
  118. return nil, nil, "", false
  119. } else if entry == nil {
  120. return nil, nil, "", true
  121. }
  122. return wikiContentsByEntry(ctx, entry), entry, pageFilename, false
  123. }
  124. func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
  125. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  126. if err != nil {
  127. if !git.IsErrNotExist(err) {
  128. ctx.ServerError("GetBranchCommit", err)
  129. }
  130. return nil, nil
  131. }
  132. // Get page list.
  133. entries, err := commit.ListEntries()
  134. if err != nil {
  135. if wikiRepo != nil {
  136. wikiRepo.Close()
  137. }
  138. ctx.ServerError("ListEntries", err)
  139. return nil, nil
  140. }
  141. pages := make([]PageMeta, 0, len(entries))
  142. for _, entry := range entries {
  143. if !entry.IsRegular() {
  144. continue
  145. }
  146. wikiName, err := models.WikiFilenameToName(entry.Name())
  147. if err != nil {
  148. if models.IsErrWikiInvalidFileName(err) {
  149. continue
  150. }
  151. if wikiRepo != nil {
  152. wikiRepo.Close()
  153. }
  154. ctx.ServerError("WikiFilenameToName", err)
  155. return nil, nil
  156. } else if wikiName == "_Sidebar" || wikiName == "_Footer" {
  157. continue
  158. }
  159. pages = append(pages, PageMeta{
  160. Name: wikiName,
  161. SubURL: models.WikiNameToSubURL(wikiName),
  162. })
  163. }
  164. ctx.Data["Pages"] = pages
  165. // get requested pagename
  166. pageName := models.NormalizeWikiName(ctx.Params(":page"))
  167. if len(pageName) == 0 {
  168. pageName = "Home"
  169. }
  170. ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName)
  171. ctx.Data["old_title"] = pageName
  172. ctx.Data["Title"] = pageName
  173. ctx.Data["title"] = pageName
  174. ctx.Data["RequireHighlightJS"] = true
  175. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  176. data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
  177. if noEntry {
  178. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  179. }
  180. if entry == nil || ctx.Written() {
  181. if wikiRepo != nil {
  182. wikiRepo.Close()
  183. }
  184. return nil, nil
  185. }
  186. sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
  187. if ctx.Written() {
  188. if wikiRepo != nil {
  189. wikiRepo.Close()
  190. }
  191. return nil, nil
  192. }
  193. footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
  194. if ctx.Written() {
  195. if wikiRepo != nil {
  196. wikiRepo.Close()
  197. }
  198. return nil, nil
  199. }
  200. metas := ctx.Repo.Repository.ComposeMetas()
  201. ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
  202. ctx.Data["sidebarPresent"] = sidebarContent != nil
  203. ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas)
  204. ctx.Data["footerPresent"] = footerContent != nil
  205. ctx.Data["footerContent"] = markdown.RenderWiki(footerContent, ctx.Repo.RepoLink, metas)
  206. // get commit count - wiki revisions
  207. commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
  208. ctx.Data["CommitCount"] = commitsCount
  209. return wikiRepo, entry
  210. }
  211. func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
  212. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  213. if err != nil {
  214. if wikiRepo != nil {
  215. wikiRepo.Close()
  216. }
  217. if !git.IsErrNotExist(err) {
  218. ctx.ServerError("GetBranchCommit", err)
  219. }
  220. return nil, nil
  221. }
  222. // get requested pagename
  223. pageName := models.NormalizeWikiName(ctx.Params(":page"))
  224. if len(pageName) == 0 {
  225. pageName = "Home"
  226. }
  227. ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName)
  228. ctx.Data["old_title"] = pageName
  229. ctx.Data["Title"] = pageName
  230. ctx.Data["title"] = pageName
  231. ctx.Data["RequireHighlightJS"] = true
  232. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  233. data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
  234. if noEntry {
  235. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  236. }
  237. if entry == nil || ctx.Written() {
  238. if wikiRepo != nil {
  239. wikiRepo.Close()
  240. }
  241. return nil, nil
  242. }
  243. ctx.Data["content"] = string(data)
  244. ctx.Data["sidebarPresent"] = false
  245. ctx.Data["sidebarContent"] = ""
  246. ctx.Data["footerPresent"] = false
  247. ctx.Data["footerContent"] = ""
  248. // get commit count - wiki revisions
  249. commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
  250. ctx.Data["CommitCount"] = commitsCount
  251. // get page
  252. page := ctx.QueryInt("page")
  253. if page <= 1 {
  254. page = 1
  255. }
  256. // get Commit Count
  257. commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page)
  258. if err != nil {
  259. if wikiRepo != nil {
  260. wikiRepo.Close()
  261. }
  262. ctx.ServerError("CommitsByFileAndRangeNoFollow", err)
  263. return nil, nil
  264. }
  265. commitsHistory = models.ValidateCommitsWithEmails(commitsHistory)
  266. commitsHistory = models.ParseCommitsWithSignature(commitsHistory)
  267. ctx.Data["Commits"] = commitsHistory
  268. pager := context.NewPagination(int(commitsCount), git.CommitsRangeSize, page, 5)
  269. pager.SetDefaultParams(ctx)
  270. ctx.Data["Page"] = pager
  271. return wikiRepo, entry
  272. }
  273. func renderEditPage(ctx *context.Context) {
  274. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  275. if err != nil {
  276. if wikiRepo != nil {
  277. wikiRepo.Close()
  278. }
  279. if !git.IsErrNotExist(err) {
  280. ctx.ServerError("GetBranchCommit", err)
  281. }
  282. return
  283. }
  284. defer func() {
  285. if wikiRepo != nil {
  286. wikiRepo.Close()
  287. }
  288. }()
  289. // get requested pagename
  290. pageName := models.NormalizeWikiName(ctx.Params(":page"))
  291. if len(pageName) == 0 {
  292. pageName = "Home"
  293. }
  294. ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName)
  295. ctx.Data["old_title"] = pageName
  296. ctx.Data["Title"] = pageName
  297. ctx.Data["title"] = pageName
  298. ctx.Data["RequireHighlightJS"] = true
  299. //lookup filename in wiki - get filecontent, gitTree entry , real filename
  300. data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName)
  301. if noEntry {
  302. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
  303. }
  304. if entry == nil || ctx.Written() {
  305. return
  306. }
  307. ctx.Data["content"] = string(data)
  308. ctx.Data["sidebarPresent"] = false
  309. ctx.Data["sidebarContent"] = ""
  310. ctx.Data["footerPresent"] = false
  311. ctx.Data["footerContent"] = ""
  312. }
  313. // Wiki renders single wiki page
  314. func Wiki(ctx *context.Context) {
  315. ctx.Data["PageIsWiki"] = true
  316. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  317. if !ctx.Repo.Repository.HasWiki() {
  318. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  319. ctx.HTML(200, tplWikiStart)
  320. return
  321. }
  322. wikiRepo, entry := renderViewPage(ctx)
  323. if ctx.Written() {
  324. if wikiRepo != nil {
  325. wikiRepo.Close()
  326. }
  327. return
  328. }
  329. defer func() {
  330. if wikiRepo != nil {
  331. wikiRepo.Close()
  332. }
  333. }()
  334. if entry == nil {
  335. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  336. ctx.HTML(200, tplWikiStart)
  337. return
  338. }
  339. wikiPath := entry.Name()
  340. if markup.Type(wikiPath) != markdown.MarkupName {
  341. ext := strings.ToUpper(filepath.Ext(wikiPath))
  342. ctx.Data["FormatWarning"] = fmt.Sprintf("%s rendering is not supported at the moment. Rendered as Markdown.", ext)
  343. }
  344. // Get last change information.
  345. lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
  346. if err != nil {
  347. ctx.ServerError("GetCommitByPath", err)
  348. return
  349. }
  350. ctx.Data["Author"] = lastCommit.Author
  351. ctx.HTML(200, tplWikiView)
  352. }
  353. // WikiRevision renders file revision list of wiki page
  354. func WikiRevision(ctx *context.Context) {
  355. ctx.Data["PageIsWiki"] = true
  356. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  357. if !ctx.Repo.Repository.HasWiki() {
  358. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  359. ctx.HTML(200, tplWikiStart)
  360. return
  361. }
  362. wikiRepo, entry := renderRevisionPage(ctx)
  363. if ctx.Written() {
  364. if wikiRepo != nil {
  365. wikiRepo.Close()
  366. }
  367. return
  368. }
  369. defer func() {
  370. if wikiRepo != nil {
  371. wikiRepo.Close()
  372. }
  373. }()
  374. if entry == nil {
  375. ctx.Data["Title"] = ctx.Tr("repo.wiki")
  376. ctx.HTML(200, tplWikiStart)
  377. return
  378. }
  379. // Get last change information.
  380. wikiPath := entry.Name()
  381. lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
  382. if err != nil {
  383. ctx.ServerError("GetCommitByPath", err)
  384. return
  385. }
  386. ctx.Data["Author"] = lastCommit.Author
  387. ctx.HTML(200, tplWikiRevision)
  388. }
  389. // WikiPages render wiki pages list page
  390. func WikiPages(ctx *context.Context) {
  391. if !ctx.Repo.Repository.HasWiki() {
  392. ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
  393. return
  394. }
  395. ctx.Data["Title"] = ctx.Tr("repo.wiki.pages")
  396. ctx.Data["PageIsWiki"] = true
  397. ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
  398. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  399. if err != nil {
  400. if wikiRepo != nil {
  401. wikiRepo.Close()
  402. }
  403. return
  404. }
  405. entries, err := commit.ListEntries()
  406. if err != nil {
  407. if wikiRepo != nil {
  408. wikiRepo.Close()
  409. }
  410. ctx.ServerError("ListEntries", err)
  411. return
  412. }
  413. pages := make([]PageMeta, 0, len(entries))
  414. for _, entry := range entries {
  415. if !entry.IsRegular() {
  416. continue
  417. }
  418. c, err := wikiRepo.GetCommitByPath(entry.Name())
  419. if err != nil {
  420. if wikiRepo != nil {
  421. wikiRepo.Close()
  422. }
  423. ctx.ServerError("GetCommit", err)
  424. return
  425. }
  426. wikiName, err := models.WikiFilenameToName(entry.Name())
  427. if err != nil {
  428. if models.IsErrWikiInvalidFileName(err) {
  429. continue
  430. }
  431. if wikiRepo != nil {
  432. wikiRepo.Close()
  433. }
  434. ctx.ServerError("WikiFilenameToName", err)
  435. return
  436. }
  437. pages = append(pages, PageMeta{
  438. Name: wikiName,
  439. SubURL: models.WikiNameToSubURL(wikiName),
  440. UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()),
  441. })
  442. }
  443. ctx.Data["Pages"] = pages
  444. defer func() {
  445. if wikiRepo != nil {
  446. wikiRepo.Close()
  447. }
  448. }()
  449. ctx.HTML(200, tplWikiPages)
  450. }
  451. // WikiRaw outputs raw blob requested by user (image for example)
  452. func WikiRaw(ctx *context.Context) {
  453. wikiRepo, commit, err := findWikiRepoCommit(ctx)
  454. if err != nil {
  455. if wikiRepo != nil {
  456. return
  457. }
  458. }
  459. providedPath := ctx.Params("*")
  460. var entry *git.TreeEntry
  461. if commit != nil {
  462. // Try to find a file with that name
  463. entry, err = findEntryForFile(commit, providedPath)
  464. if err != nil {
  465. ctx.ServerError("findFile", err)
  466. return
  467. }
  468. if entry == nil {
  469. // Try to find a wiki page with that name
  470. if strings.HasSuffix(providedPath, ".md") {
  471. providedPath = providedPath[:len(providedPath)-3]
  472. }
  473. wikiPath := models.WikiNameToFilename(providedPath)
  474. entry, err = findEntryForFile(commit, wikiPath)
  475. if err != nil {
  476. ctx.ServerError("findFile", err)
  477. return
  478. }
  479. }
  480. }
  481. if entry != nil {
  482. if err = ServeBlob(ctx, entry.Blob()); err != nil {
  483. ctx.ServerError("ServeBlob", err)
  484. }
  485. return
  486. }
  487. ctx.NotFound("findEntryForFile", nil)
  488. }
  489. // NewWiki render wiki create page
  490. func NewWiki(ctx *context.Context) {
  491. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  492. ctx.Data["PageIsWiki"] = true
  493. ctx.Data["RequireSimpleMDE"] = true
  494. if !ctx.Repo.Repository.HasWiki() {
  495. ctx.Data["title"] = "Home"
  496. }
  497. ctx.HTML(200, tplWikiNew)
  498. }
  499. // NewWikiPost response for wiki create request
  500. func NewWikiPost(ctx *context.Context, form auth.NewWikiForm) {
  501. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  502. ctx.Data["PageIsWiki"] = true
  503. ctx.Data["RequireSimpleMDE"] = true
  504. if ctx.HasError() {
  505. ctx.HTML(200, tplWikiNew)
  506. return
  507. }
  508. if util.IsEmptyString(form.Title) {
  509. ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), tplWikiNew, form)
  510. return
  511. }
  512. wikiName := models.NormalizeWikiName(form.Title)
  513. if err := ctx.Repo.Repository.AddWikiPage(ctx.User, wikiName, form.Content, form.Message); err != nil {
  514. if models.IsErrWikiReservedName(err) {
  515. ctx.Data["Err_Title"] = true
  516. ctx.RenderWithErr(ctx.Tr("repo.wiki.reserved_page", wikiName), tplWikiNew, &form)
  517. } else if models.IsErrWikiAlreadyExist(err) {
  518. ctx.Data["Err_Title"] = true
  519. ctx.RenderWithErr(ctx.Tr("repo.wiki.page_already_exists"), tplWikiNew, &form)
  520. } else {
  521. ctx.ServerError("AddWikiPage", err)
  522. }
  523. return
  524. }
  525. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.WikiNameToSubURL(wikiName))
  526. }
  527. // EditWiki render wiki modify page
  528. func EditWiki(ctx *context.Context) {
  529. ctx.Data["PageIsWiki"] = true
  530. ctx.Data["PageIsWikiEdit"] = true
  531. ctx.Data["RequireSimpleMDE"] = true
  532. if !ctx.Repo.Repository.HasWiki() {
  533. ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
  534. return
  535. }
  536. renderEditPage(ctx)
  537. if ctx.Written() {
  538. return
  539. }
  540. ctx.HTML(200, tplWikiNew)
  541. }
  542. // EditWikiPost response for wiki modify request
  543. func EditWikiPost(ctx *context.Context, form auth.NewWikiForm) {
  544. ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
  545. ctx.Data["PageIsWiki"] = true
  546. ctx.Data["RequireSimpleMDE"] = true
  547. if ctx.HasError() {
  548. ctx.HTML(200, tplWikiNew)
  549. return
  550. }
  551. oldWikiName := models.NormalizeWikiName(ctx.Params(":page"))
  552. newWikiName := models.NormalizeWikiName(form.Title)
  553. if err := ctx.Repo.Repository.EditWikiPage(ctx.User, oldWikiName, newWikiName, form.Content, form.Message); err != nil {
  554. ctx.ServerError("EditWikiPage", err)
  555. return
  556. }
  557. ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.WikiNameToSubURL(newWikiName))
  558. }
  559. // DeleteWikiPagePost delete wiki page
  560. func DeleteWikiPagePost(ctx *context.Context) {
  561. wikiName := models.NormalizeWikiName(ctx.Params(":page"))
  562. if len(wikiName) == 0 {
  563. wikiName = "Home"
  564. }
  565. if err := ctx.Repo.Repository.DeleteWikiPage(ctx.User, wikiName); err != nil {
  566. ctx.ServerError("DeleteWikiPage", err)
  567. return
  568. }
  569. ctx.JSON(200, map[string]interface{}{
  570. "redirect": ctx.Repo.RepoLink + "/wiki/",
  571. })
  572. }