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

repo.go 9.7 kB

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