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.

351 lines
9.3 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. // Copyright 2014 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. "path"
  7. "path/filepath"
  8. "strings"
  9. "github.com/codegangsta/martini"
  10. "github.com/gogits/webdav"
  11. "github.com/gogits/gogs/models"
  12. "github.com/gogits/gogs/modules/auth"
  13. "github.com/gogits/gogs/modules/base"
  14. "github.com/gogits/gogs/modules/log"
  15. "github.com/gogits/gogs/modules/middleware"
  16. )
  17. func Create(ctx *middleware.Context, form auth.CreateRepoForm) {
  18. ctx.Data["Title"] = "Create repository"
  19. ctx.Data["PageIsNewRepo"] = true // For navbar arrow.
  20. ctx.Data["LanguageIgns"] = models.LanguageIgns
  21. ctx.Data["Licenses"] = models.Licenses
  22. if ctx.Req.Method == "GET" {
  23. ctx.HTML(200, "repo/create")
  24. return
  25. }
  26. if ctx.HasError() {
  27. ctx.HTML(200, "repo/create")
  28. return
  29. }
  30. _, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
  31. form.Language, form.License, form.Visibility == "private", form.InitReadme == "on")
  32. if err == nil {
  33. log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
  34. ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName)
  35. return
  36. } else if err == models.ErrRepoAlreadyExist {
  37. ctx.RenderWithErr("Repository name has already been used", "repo/create", &form)
  38. return
  39. } else if err == models.ErrRepoNameIllegal {
  40. ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/create", &form)
  41. return
  42. }
  43. ctx.Handle(200, "repo.Create", err)
  44. }
  45. func Single(ctx *middleware.Context, params martini.Params) {
  46. if !ctx.Repo.IsValid {
  47. return
  48. }
  49. // Get tree path
  50. treename := params["_1"]
  51. if len(treename) > 0 && treename[len(treename)-1] == '/' {
  52. ctx.Redirect("/" + ctx.Repo.Owner.LowerName + "/" +
  53. ctx.Repo.Repository.Name + "/src/" + params["branchname"] + "/" + treename[:len(treename)-1])
  54. return
  55. }
  56. ctx.Data["IsRepoToolbarSource"] = true
  57. // Branches.
  58. brs, err := models.GetBranches(params["username"], params["reponame"])
  59. if err != nil {
  60. //log.Error("repo.Single(GetBranches): %v", err)
  61. ctx.Handle(404, "repo.Single(GetBranches)", err)
  62. return
  63. } else if ctx.Repo.Repository.IsBare {
  64. ctx.Data["IsBareRepo"] = true
  65. ctx.HTML(200, "repo/single")
  66. return
  67. }
  68. ctx.Data["Branches"] = brs
  69. repoFile, err := models.GetTargetFile(params["username"], params["reponame"],
  70. params["branchname"], params["commitid"], treename)
  71. if err != nil && err != models.ErrRepoFileNotExist {
  72. //log.Error("repo.Single(GetTargetFile): %v", err)
  73. ctx.Handle(404, "repo.Single(GetTargetFile)", err)
  74. return
  75. }
  76. branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + params["branchname"]
  77. rawLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/raw/" + params["branchname"]
  78. if len(treename) != 0 && repoFile == nil {
  79. ctx.Handle(404, "repo.Single", nil)
  80. return
  81. }
  82. if repoFile != nil && repoFile.IsFile() {
  83. if blob, err := repoFile.LookupBlob(); err != nil {
  84. ctx.Handle(404, "repo.Single(repoFile.LookupBlob)", err)
  85. } else {
  86. ctx.Data["FileSize"] = repoFile.Size
  87. ctx.Data["IsFile"] = true
  88. ctx.Data["FileName"] = repoFile.Name
  89. ext := path.Ext(repoFile.Name)
  90. if len(ext) > 0 {
  91. ext = ext[1:]
  92. }
  93. ctx.Data["FileExt"] = ext
  94. ctx.Data["FileLink"] = rawLink + "/" + treename
  95. data := blob.Contents()
  96. _, isTextFile := base.IsTextFile(data)
  97. ctx.Data["FileIsText"] = isTextFile
  98. readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name)
  99. ctx.Data["ReadmeExist"] = readmeExist
  100. if readmeExist {
  101. ctx.Data["FileContent"] = string(base.RenderMarkdown(data, ""))
  102. } else {
  103. if isTextFile {
  104. ctx.Data["FileContent"] = string(data)
  105. }
  106. }
  107. }
  108. } else {
  109. // Directory and file list.
  110. files, err := models.GetReposFiles(params["username"], params["reponame"],
  111. params["branchname"], params["commitid"], treename)
  112. if err != nil {
  113. //log.Error("repo.Single(GetReposFiles): %v", err)
  114. ctx.Handle(404, "repo.Single(GetReposFiles)", err)
  115. return
  116. }
  117. ctx.Data["Files"] = files
  118. var readmeFile *models.RepoFile
  119. for _, f := range files {
  120. if !f.IsFile() || !base.IsReadmeFile(f.Name) {
  121. continue
  122. } else {
  123. readmeFile = f
  124. break
  125. }
  126. }
  127. if readmeFile != nil {
  128. ctx.Data["ReadmeInSingle"] = true
  129. ctx.Data["ReadmeExist"] = true
  130. if blob, err := readmeFile.LookupBlob(); err != nil {
  131. ctx.Handle(404, "repo.Single(readmeFile.LookupBlob)", err)
  132. return
  133. } else {
  134. ctx.Data["FileSize"] = readmeFile.Size
  135. ctx.Data["FileLink"] = rawLink + "/" + treename
  136. data := blob.Contents()
  137. _, isTextFile := base.IsTextFile(data)
  138. ctx.Data["FileIsText"] = isTextFile
  139. ctx.Data["FileName"] = readmeFile.Name
  140. if isTextFile {
  141. ctx.Data["FileContent"] = string(base.RenderMarkdown(data, branchLink))
  142. }
  143. }
  144. }
  145. }
  146. ctx.Data["Username"] = params["username"]
  147. ctx.Data["Reponame"] = params["reponame"]
  148. var treenames []string
  149. Paths := make([]string, 0)
  150. if len(treename) > 0 {
  151. treenames = strings.Split(treename, "/")
  152. for i, _ := range treenames {
  153. Paths = append(Paths, strings.Join(treenames[0:i+1], "/"))
  154. }
  155. ctx.Data["HasParentPath"] = true
  156. if len(Paths)-2 >= 0 {
  157. ctx.Data["ParentPath"] = "/" + Paths[len(Paths)-2]
  158. }
  159. }
  160. // Get latest commit according username and repo name
  161. commit, err := models.GetCommit(params["username"], params["reponame"],
  162. params["branchname"], params["commitid"])
  163. if err != nil {
  164. log.Error("repo.Single(GetCommit): %v", err)
  165. ctx.Handle(404, "repo.Single(GetCommit)", err)
  166. return
  167. }
  168. ctx.Data["LastCommit"] = commit
  169. ctx.Data["Paths"] = Paths
  170. ctx.Data["Treenames"] = treenames
  171. ctx.Data["BranchLink"] = branchLink
  172. ctx.HTML(200, "repo/single")
  173. }
  174. func SingleDownload(ctx *middleware.Context, params martini.Params) {
  175. if !ctx.Repo.IsValid {
  176. ctx.Handle(404, "repo.SingleDownload", nil)
  177. return
  178. }
  179. // Get tree path
  180. treename := params["_1"]
  181. repoFile, err := models.GetTargetFile(params["username"], params["reponame"],
  182. params["branchname"], params["commitid"], treename)
  183. if err != nil {
  184. ctx.Handle(404, "repo.SingleDownload(GetTargetFile)", err)
  185. return
  186. }
  187. blob, err := repoFile.LookupBlob()
  188. if err != nil {
  189. ctx.Handle(404, "repo.SingleDownload(LookupBlob)", err)
  190. return
  191. }
  192. data := blob.Contents()
  193. contentType, isTextFile := base.IsTextFile(data)
  194. ctx.Res.Header().Set("Content-Type", contentType)
  195. if !isTextFile {
  196. ctx.Res.Header().Set("Content-Type", contentType)
  197. ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(treename))
  198. ctx.Res.Header().Set("Content-Transfer-Encoding", "binary")
  199. }
  200. ctx.Res.Write(data)
  201. }
  202. func Http(ctx *middleware.Context, params martini.Params) {
  203. /*if !ctx.Repo.IsValid {
  204. return
  205. }*/
  206. // TODO: access check
  207. username := params["username"]
  208. reponame := params["reponame"]
  209. if strings.HasSuffix(reponame, ".git") {
  210. reponame = reponame[:len(reponame)-4]
  211. }
  212. prefix := path.Join("/", username, params["reponame"])
  213. server := &webdav.Server{
  214. Fs: webdav.Dir(models.RepoPath(username, reponame)),
  215. TrimPrefix: prefix,
  216. Listings: true,
  217. }
  218. server.ServeHTTP(ctx.ResponseWriter, ctx.Req)
  219. }
  220. func Setting(ctx *middleware.Context, params martini.Params) {
  221. if !ctx.Repo.IsOwner {
  222. ctx.Handle(404, "repo.Setting", nil)
  223. return
  224. }
  225. ctx.Data["IsRepoToolbarSetting"] = true
  226. if ctx.Repo.Repository.IsBare {
  227. ctx.Data["IsBareRepo"] = true
  228. ctx.HTML(200, "repo/setting")
  229. return
  230. }
  231. var title string
  232. if t, ok := ctx.Data["Title"].(string); ok {
  233. title = t
  234. }
  235. ctx.Data["Title"] = title + " - settings"
  236. ctx.HTML(200, "repo/setting")
  237. }
  238. func SettingPost(ctx *middleware.Context) {
  239. if !ctx.Repo.IsOwner {
  240. ctx.Error(404)
  241. return
  242. }
  243. switch ctx.Query("action") {
  244. case "update":
  245. ctx.Repo.Repository.Description = ctx.Query("desc")
  246. ctx.Repo.Repository.Website = ctx.Query("site")
  247. if err := models.UpdateRepository(ctx.Repo.Repository); err != nil {
  248. ctx.Handle(404, "repo.SettingPost(update)", err)
  249. return
  250. }
  251. ctx.Data["IsSuccess"] = true
  252. ctx.HTML(200, "repo/setting")
  253. log.Trace("%s Repository updated: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.LowerName)
  254. case "delete":
  255. if len(ctx.Repo.Repository.Name) == 0 || ctx.Repo.Repository.Name != ctx.Query("repository") {
  256. ctx.Data["ErrorMsg"] = "Please make sure you entered repository name is correct."
  257. ctx.HTML(200, "repo/setting")
  258. return
  259. }
  260. if err := models.DeleteRepository(ctx.User.Id, ctx.Repo.Repository.Id, ctx.User.LowerName); err != nil {
  261. ctx.Handle(200, "repo.Delete", err)
  262. return
  263. }
  264. log.Trace("%s Repository deleted: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.LowerName)
  265. ctx.Redirect("/")
  266. }
  267. }
  268. func Action(ctx *middleware.Context, params martini.Params) {
  269. var err error
  270. switch params["action"] {
  271. case "watch":
  272. err = models.WatchRepo(ctx.User.Id, ctx.Repo.Repository.Id, true)
  273. case "unwatch":
  274. err = models.WatchRepo(ctx.User.Id, ctx.Repo.Repository.Id, false)
  275. case "desc":
  276. if !ctx.Repo.IsOwner {
  277. ctx.Error(404)
  278. return
  279. }
  280. ctx.Repo.Repository.Description = ctx.Query("desc")
  281. ctx.Repo.Repository.Website = ctx.Query("site")
  282. err = models.UpdateRepository(ctx.Repo.Repository)
  283. }
  284. if err != nil {
  285. log.Error("repo.Action(%s): %v", params["action"], err)
  286. ctx.JSON(200, map[string]interface{}{
  287. "ok": false,
  288. "err": err.Error(),
  289. })
  290. return
  291. }
  292. ctx.JSON(200, map[string]interface{}{
  293. "ok": true,
  294. })
  295. }