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 7.4 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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 middleware
  5. import (
  6. "errors"
  7. "fmt"
  8. "net/url"
  9. "strings"
  10. "github.com/go-martini/martini"
  11. "github.com/gogits/git"
  12. "github.com/gogits/gogs/models"
  13. "github.com/gogits/gogs/modules/log"
  14. "github.com/gogits/gogs/modules/setting"
  15. )
  16. func RepoAssignment(redirect bool, args ...bool) martini.Handler {
  17. return func(ctx *Context, params martini.Params) {
  18. // valid brachname
  19. var validBranch bool
  20. // display bare quick start if it is a bare repo
  21. var displayBare bool
  22. if len(args) >= 1 {
  23. validBranch = args[0]
  24. }
  25. if len(args) >= 2 {
  26. displayBare = args[1]
  27. }
  28. var (
  29. user *models.User
  30. err error
  31. isTrueOwner bool
  32. )
  33. userName := params["username"]
  34. repoName := params["reponame"]
  35. refName := params["branchname"]
  36. // TODO: need more advanced onwership and access level check.
  37. // Collaborators who have write access can be seen as owners.
  38. if ctx.IsSigned {
  39. ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.WRITABLE)
  40. if err != nil {
  41. ctx.Handle(500, "RepoAssignment(HasAccess)", err)
  42. return
  43. }
  44. isTrueOwner = ctx.User.LowerName == strings.ToLower(userName)
  45. }
  46. if !isTrueOwner {
  47. user, err = models.GetUserByName(userName)
  48. if err != nil {
  49. if err == models.ErrUserNotExist {
  50. ctx.Handle(404, "RepoAssignment(GetUserByName)", err)
  51. return
  52. } else if redirect {
  53. ctx.Redirect("/")
  54. return
  55. }
  56. ctx.Handle(500, "RepoAssignment(GetUserByName)", err)
  57. return
  58. }
  59. } else {
  60. user = ctx.User
  61. }
  62. if user == nil {
  63. if redirect {
  64. ctx.Redirect("/")
  65. return
  66. }
  67. ctx.Handle(403, "RepoAssignment", errors.New("invliad user account for single repository"))
  68. return
  69. }
  70. ctx.Repo.Owner = user
  71. // get repository
  72. repo, err := models.GetRepositoryByName(user.Id, repoName)
  73. if err != nil {
  74. if err == models.ErrRepoNotExist {
  75. ctx.Handle(404, "RepoAssignment", err)
  76. return
  77. } else if redirect {
  78. ctx.Redirect("/")
  79. return
  80. }
  81. ctx.Handle(500, "RepoAssignment", err)
  82. return
  83. }
  84. // Check if the mirror repository owner(mirror repository doesn't have access).
  85. if ctx.IsSigned && !ctx.Repo.IsOwner && repo.OwnerId == ctx.User.Id {
  86. ctx.Repo.IsOwner = true
  87. }
  88. // Check access.
  89. if repo.IsPrivate && !ctx.Repo.IsOwner {
  90. if ctx.User == nil {
  91. ctx.Handle(404, "RepoAssignment(HasAccess)", nil)
  92. return
  93. }
  94. hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.READABLE)
  95. if err != nil {
  96. ctx.Handle(500, "RepoAssignment(HasAccess)", err)
  97. return
  98. } else if !hasAccess {
  99. ctx.Handle(404, "RepoAssignment(HasAccess)", nil)
  100. return
  101. }
  102. }
  103. ctx.Repo.HasAccess = true
  104. ctx.Data["HasAccess"] = true
  105. if repo.IsMirror {
  106. ctx.Repo.Mirror, err = models.GetMirror(repo.Id)
  107. if err != nil {
  108. ctx.Handle(500, "RepoAssignment(GetMirror)", err)
  109. return
  110. }
  111. ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval
  112. }
  113. repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
  114. repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
  115. ctx.Repo.Repository = repo
  116. ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
  117. gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
  118. if err != nil {
  119. ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
  120. return
  121. }
  122. ctx.Repo.GitRepo = gitRepo
  123. ctx.Repo.RepoLink = "/" + user.Name + "/" + repo.Name
  124. tags, err := ctx.Repo.GitRepo.GetTags()
  125. if err != nil {
  126. ctx.Handle(500, "RepoAssignment(GetTags))", err)
  127. return
  128. }
  129. ctx.Repo.Repository.NumTags = len(tags)
  130. ctx.Data["Title"] = user.Name + "/" + repo.Name
  131. ctx.Data["Repository"] = repo
  132. ctx.Data["Owner"] = user
  133. ctx.Data["RepoLink"] = ctx.Repo.RepoLink
  134. ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
  135. ctx.Data["BranchName"] = ""
  136. if setting.SshPort != 22 {
  137. ctx.Repo.CloneLink.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", setting.RunUser, setting.Domain, user.LowerName, repo.LowerName)
  138. } else {
  139. ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.Domain, user.LowerName, repo.LowerName)
  140. }
  141. ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, user.LowerName, repo.LowerName)
  142. ctx.Data["CloneLink"] = ctx.Repo.CloneLink
  143. if ctx.Repo.Repository.IsGoget {
  144. ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", setting.AppUrl, user.LowerName, repo.LowerName)
  145. ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", setting.Domain, user.LowerName, repo.LowerName)
  146. }
  147. // when repo is bare, not valid branch
  148. if !ctx.Repo.Repository.IsBare && validBranch {
  149. detect:
  150. if len(refName) > 0 {
  151. if gitRepo.IsBranchExist(refName) {
  152. ctx.Repo.IsBranch = true
  153. ctx.Repo.BranchName = refName
  154. ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(refName)
  155. if err != nil {
  156. ctx.Handle(404, "RepoAssignment invalid branch", nil)
  157. return
  158. }
  159. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  160. } else if gitRepo.IsTagExist(refName) {
  161. ctx.Repo.IsTag = true
  162. ctx.Repo.BranchName = refName
  163. ctx.Repo.Tag, err = gitRepo.GetTag(refName)
  164. if err != nil {
  165. ctx.Handle(404, "RepoAssignment invalid tag", nil)
  166. return
  167. }
  168. ctx.Repo.Commit, _ = ctx.Repo.Tag.Commit()
  169. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  170. } else if len(refName) == 40 {
  171. ctx.Repo.IsCommit = true
  172. ctx.Repo.CommitId = refName
  173. ctx.Repo.BranchName = refName
  174. ctx.Repo.Commit, err = gitRepo.GetCommit(refName)
  175. if err != nil {
  176. ctx.Handle(404, "RepoAssignment invalid commit", nil)
  177. return
  178. }
  179. } else {
  180. ctx.Handle(404, "RepoAssignment invalid repo", nil)
  181. return
  182. }
  183. } else {
  184. if len(refName) == 0 {
  185. if gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  186. refName = ctx.Repo.Repository.DefaultBranch
  187. } else {
  188. brs, err := gitRepo.GetBranches()
  189. if err != nil {
  190. ctx.Handle(500, "RepoAssignment(GetBranches))", err)
  191. return
  192. }
  193. refName = brs[0]
  194. }
  195. }
  196. goto detect
  197. }
  198. ctx.Data["IsBranch"] = ctx.Repo.IsBranch
  199. ctx.Data["IsCommit"] = ctx.Repo.IsCommit
  200. }
  201. log.Debug("displayBare: %v; IsBare: %v", displayBare, ctx.Repo.Repository.IsBare)
  202. // repo is bare and display enable
  203. if displayBare && ctx.Repo.Repository.IsBare {
  204. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  205. ctx.HTML(200, "repo/single_bare")
  206. return
  207. }
  208. if ctx.IsSigned {
  209. ctx.Repo.IsWatching = models.IsWatching(ctx.User.Id, repo.Id)
  210. }
  211. ctx.Data["BranchName"] = ctx.Repo.BranchName
  212. ctx.Data["TagName"] = ctx.Repo.TagName
  213. brs, err := ctx.Repo.GitRepo.GetBranches()
  214. if err != nil {
  215. log.Error("RepoAssignment(GetBranches): %v", err)
  216. }
  217. ctx.Data["Branches"] = brs
  218. ctx.Data["CommitId"] = ctx.Repo.CommitId
  219. ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching
  220. }
  221. }
  222. func RequireOwner() martini.Handler {
  223. return func(ctx *Context) {
  224. if !ctx.Repo.IsOwner {
  225. if !ctx.IsSigned {
  226. ctx.SetCookie("redirect_to", "/"+url.QueryEscape(ctx.Req.RequestURI))
  227. ctx.Redirect("/user/login")
  228. return
  229. }
  230. ctx.Handle(404, ctx.Req.RequestURI, nil)
  231. return
  232. }
  233. }
  234. }