contents.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2020 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "encoding/base64"
  7. "fmt"
  8. "gogs.io/gogs/internal/context"
  9. "gogs.io/gogs/internal/gitutil"
  10. )
  11. type repoContent struct {
  12. Type string `json:"type"`
  13. Target string `json:"target,omitempty"`
  14. SubmoduleGitURL string `json:"submodule_git_url,omitempty"`
  15. Encoding string `json:"encoding,omitempty"`
  16. Size int64 `json:"size"`
  17. Name string `json:"name"`
  18. Path string `json:"path"`
  19. Content string `json:"content,omitempty"`
  20. Sha string `json:"sha"`
  21. URL string `json:"url"`
  22. GitURL string `json:"git_url"`
  23. HTMLURL string `json:"html_url"`
  24. DownloadURL string `json:"download_url"`
  25. Links Links `json:"_links"`
  26. }
  27. type Links struct {
  28. Git string `json:"git"`
  29. Self string `json:"self"`
  30. HTML string `json:"html"`
  31. }
  32. func GetContents(c *context.APIContext) {
  33. treeEntry, err := c.Repo.Commit.TreeEntry(c.Repo.TreePath)
  34. if err != nil {
  35. c.NotFoundOrServerError("get tree entry", gitutil.IsErrRevisionNotExist, err)
  36. return
  37. }
  38. username := c.Params(":username")
  39. reponame := c.Params(":reponame")
  40. // TODO: figure out the best way to do this
  41. // :base-url/:username/:project/raw/:refs/:path
  42. templateDownloadURL := "%s/%s/%s/raw/%s"
  43. // :base-url/repos/:username/:project/contents/:path
  44. templateSelfLink := "%s/repos/%s/%s/contents/%s"
  45. // :baseurl/repos/:username/:project/git/trees/:sha
  46. templateGitURLLink := "%s/repos/%s/%s/trees/%s"
  47. // :baseurl/repos/:username/:project/tree/:sha
  48. templateHTMLLLink := "%s/repos/%s/%s/tree/%s"
  49. gitURL := fmt.Sprintf(templateGitURLLink, c.BaseURL, username, reponame, treeEntry.ID().String())
  50. htmlURL := fmt.Sprintf(templateHTMLLLink, c.BaseURL, username, reponame, treeEntry.ID().String())
  51. selfURL := fmt.Sprintf(templateSelfLink, c.BaseURL, username, reponame, c.Repo.TreePath)
  52. // TODO(unknwon): Make a treeEntryToRepoContent helper.
  53. contents := &repoContent{
  54. Size: treeEntry.Size(),
  55. Name: treeEntry.Name(),
  56. Path: c.Repo.TreePath,
  57. Sha: treeEntry.ID().String(),
  58. URL: selfURL,
  59. GitURL: gitURL,
  60. HTMLURL: htmlURL,
  61. DownloadURL: fmt.Sprintf(templateDownloadURL, c.BaseURL, username, reponame, c.Repo.TreePath),
  62. Links: Links{
  63. Git: gitURL,
  64. Self: selfURL,
  65. HTML: htmlURL,
  66. },
  67. }
  68. // A tree entry can only be one of the following types:
  69. // 1. Tree (directory)
  70. // 2. SubModule
  71. // 3. SymLink
  72. // 4. Blob (file)
  73. if treeEntry.IsCommit() {
  74. // TODO(unknwon): submoduleURL is not set as current git-module doesn't handle it properly
  75. contents.Type = "submodule"
  76. c.JSONSuccess(contents)
  77. return
  78. } else if treeEntry.IsSymlink() {
  79. contents.Type = "symlink"
  80. blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
  81. if err != nil {
  82. c.ServerError("GetBlobByPath", err)
  83. return
  84. }
  85. p, err := blob.Bytes()
  86. if err != nil {
  87. c.ServerError("Data", err)
  88. return
  89. }
  90. contents.Target = string(p)
  91. c.JSONSuccess(contents)
  92. return
  93. } else if treeEntry.IsBlob() {
  94. blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
  95. if err != nil {
  96. c.ServerError("GetBlobByPath", err)
  97. return
  98. }
  99. p, err := blob.Bytes()
  100. if err != nil {
  101. c.ServerError("Data", err)
  102. return
  103. }
  104. contents.Content = base64.StdEncoding.EncodeToString(p)
  105. contents.Type = "file"
  106. c.JSONSuccess(contents)
  107. return
  108. }
  109. // TODO: treeEntry.IsExec()
  110. // treeEntry is a directory
  111. dirTree, err := c.Repo.GitRepo.LsTree(treeEntry.ID().String())
  112. if err != nil {
  113. c.NotFoundOrServerError("get tree", gitutil.IsErrRevisionNotExist, err)
  114. return
  115. }
  116. entries, err := dirTree.Entries()
  117. if err != nil {
  118. c.NotFoundOrServerError("list entries", gitutil.IsErrRevisionNotExist, err)
  119. return
  120. }
  121. if len(entries) == 0 {
  122. c.JSONSuccess([]string{})
  123. return
  124. }
  125. var results = make([]*repoContent, 0, len(entries))
  126. for _, entry := range entries {
  127. gitURL := fmt.Sprintf(templateGitURLLink, c.BaseURL, username, reponame, entry.ID().String())
  128. htmlURL := fmt.Sprintf(templateHTMLLLink, c.BaseURL, username, reponame, entry.ID().String())
  129. selfURL := fmt.Sprintf(templateSelfLink, c.BaseURL, username, reponame, c.Repo.TreePath)
  130. var contentType string
  131. if entry.IsTree() {
  132. contentType = "dir"
  133. } else if entry.IsCommit() {
  134. // TODO(unknwon): submoduleURL is not set as current git-module doesn't handle it properly
  135. contentType = "submodule"
  136. } else if entry.IsSymlink() {
  137. contentType = "symlink"
  138. blob, err := c.Repo.Commit.Blob(c.Repo.TreePath)
  139. if err != nil {
  140. c.ServerError("GetBlobByPath", err)
  141. return
  142. }
  143. p, err := blob.Bytes()
  144. if err != nil {
  145. c.ServerError("Data", err)
  146. return
  147. }
  148. contents.Target = string(p)
  149. } else {
  150. contentType = "file"
  151. }
  152. results = append(results, &repoContent{
  153. Type: contentType,
  154. Size: entry.Size(),
  155. Name: entry.Name(),
  156. Path: c.Repo.TreePath,
  157. Sha: entry.ID().String(),
  158. URL: selfURL,
  159. GitURL: gitURL,
  160. HTMLURL: htmlURL,
  161. DownloadURL: fmt.Sprintf(templateDownloadURL, c.BaseURL, username, reponame, c.Repo.TreePath),
  162. Links: Links{
  163. Git: gitURL,
  164. Self: selfURL,
  165. HTML: htmlURL,
  166. },
  167. })
  168. }
  169. c.JSONSuccess(results)
  170. }