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