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