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.6 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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. log.Error(4, "GetUserByName", err)
  54. ctx.Redirect("/")
  55. } else {
  56. ctx.Handle(500, "GetUserByName", err)
  57. }
  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 {
  94. if repo.OwnerId == ctx.User.Id {
  95. ctx.Repo.IsOwner = true
  96. }
  97. // Check if current user has admin permission to repository.
  98. if u.IsOrganization() {
  99. auth, err := models.GetHighestAuthorize(u.Id, ctx.User.Id, 0, repo.Id)
  100. if err != nil {
  101. ctx.Handle(500, "GetHighestAuthorize", err)
  102. return
  103. }
  104. if auth == models.ORG_ADMIN {
  105. ctx.Repo.IsOwner = true
  106. ctx.Repo.IsAdmin = true
  107. }
  108. }
  109. }
  110. // Check access.
  111. if repo.IsPrivate && !ctx.Repo.IsOwner {
  112. if ctx.User == nil {
  113. ctx.Handle(404, "HasAccess", nil)
  114. return
  115. }
  116. hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.READABLE)
  117. if err != nil {
  118. ctx.Handle(500, "HasAccess", err)
  119. return
  120. } else if !hasAccess {
  121. ctx.Handle(404, "HasAccess", nil)
  122. return
  123. }
  124. }
  125. ctx.Repo.HasAccess = true
  126. ctx.Data["HasAccess"] = true
  127. if repo.IsMirror {
  128. ctx.Repo.Mirror, err = models.GetMirror(repo.Id)
  129. if err != nil {
  130. ctx.Handle(500, "GetMirror", err)
  131. return
  132. }
  133. ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval
  134. }
  135. repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
  136. repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
  137. ctx.Repo.Repository = repo
  138. ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
  139. gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
  140. if err != nil {
  141. ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
  142. return
  143. }
  144. ctx.Repo.GitRepo = gitRepo
  145. ctx.Repo.RepoLink = "/" + u.Name + "/" + repo.Name
  146. ctx.Data["RepoLink"] = ctx.Repo.RepoLink
  147. tags, err := ctx.Repo.GitRepo.GetTags()
  148. if err != nil {
  149. ctx.Handle(500, "GetTags", err)
  150. return
  151. }
  152. ctx.Repo.Repository.NumTags = len(tags)
  153. ctx.Data["Title"] = u.Name + "/" + repo.Name
  154. ctx.Data["Repository"] = repo
  155. ctx.Data["Owner"] = ctx.Repo.Repository.Owner
  156. ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
  157. ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner
  158. if setting.SshPort != 22 {
  159. ctx.Repo.CloneLink.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.Domain, setting.SshPort, u.LowerName, repo.LowerName)
  160. } else {
  161. ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.Domain, u.LowerName, repo.LowerName)
  162. }
  163. ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, u.LowerName, repo.LowerName)
  164. ctx.Data["CloneLink"] = ctx.Repo.CloneLink
  165. if ctx.Repo.Repository.IsGoget {
  166. ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", setting.AppUrl, u.LowerName, repo.LowerName)
  167. ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", setting.Domain, u.LowerName, repo.LowerName)
  168. }
  169. // when repo is bare, not valid branch
  170. if !ctx.Repo.Repository.IsBare && validBranch {
  171. detect:
  172. if len(refName) > 0 {
  173. if gitRepo.IsBranchExist(refName) {
  174. ctx.Repo.IsBranch = true
  175. ctx.Repo.BranchName = refName
  176. ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(refName)
  177. if err != nil {
  178. ctx.Handle(404, "RepoAssignment invalid branch", nil)
  179. return
  180. }
  181. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  182. } else if gitRepo.IsTagExist(refName) {
  183. ctx.Repo.IsTag = true
  184. ctx.Repo.BranchName = refName
  185. ctx.Repo.Tag, err = gitRepo.GetTag(refName)
  186. if err != nil {
  187. ctx.Handle(404, "RepoAssignment invalid tag", nil)
  188. return
  189. }
  190. ctx.Repo.Commit, _ = ctx.Repo.Tag.Commit()
  191. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  192. } else if len(refName) == 40 {
  193. ctx.Repo.IsCommit = true
  194. ctx.Repo.CommitId = refName
  195. ctx.Repo.BranchName = refName
  196. ctx.Repo.Commit, err = gitRepo.GetCommit(refName)
  197. if err != nil {
  198. ctx.Handle(404, "RepoAssignment invalid commit", nil)
  199. return
  200. }
  201. } else {
  202. ctx.Handle(404, "RepoAssignment invalid repo", errors.New("branch or tag not exist"))
  203. return
  204. }
  205. } else {
  206. if len(refName) == 0 {
  207. if gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  208. refName = ctx.Repo.Repository.DefaultBranch
  209. } else {
  210. brs, err := gitRepo.GetBranches()
  211. if err != nil {
  212. ctx.Handle(500, "GetBranches", err)
  213. return
  214. }
  215. refName = brs[0]
  216. }
  217. }
  218. goto detect
  219. }
  220. ctx.Data["IsBranch"] = ctx.Repo.IsBranch
  221. ctx.Data["IsCommit"] = ctx.Repo.IsCommit
  222. ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
  223. if err != nil {
  224. ctx.Handle(500, "CommitsCount", err)
  225. return
  226. }
  227. ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
  228. }
  229. // repo is bare and display enable
  230. if ctx.Repo.Repository.IsBare {
  231. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  232. if displayBare {
  233. ctx.HTML(200, "repo/bare")
  234. }
  235. return
  236. }
  237. if ctx.IsSigned {
  238. ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.Id, repo.Id)
  239. ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.Id, repo.Id)
  240. }
  241. ctx.Data["TagName"] = ctx.Repo.TagName
  242. brs, err := ctx.Repo.GitRepo.GetBranches()
  243. if err != nil {
  244. log.Error(4, "GetBranches: %v", err)
  245. }
  246. ctx.Data["Branches"] = brs
  247. ctx.Data["BrancheCount"] = len(brs)
  248. // If not branch selected, try default one.
  249. // If default branch doesn't exists, fall back to some other branch.
  250. if ctx.Repo.BranchName == "" {
  251. if ctx.Repo.Repository.DefaultBranch != "" && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  252. ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
  253. } else if len(brs) > 0 {
  254. ctx.Repo.BranchName = brs[0]
  255. }
  256. }
  257. ctx.Data["BranchName"] = ctx.Repo.BranchName
  258. ctx.Data["CommitId"] = ctx.Repo.CommitId
  259. }
  260. }
  261. func RequireTrueOwner() macaron.Handler {
  262. return func(ctx *Context) {
  263. if !ctx.Repo.IsTrueOwner && !ctx.Repo.IsAdmin {
  264. if !ctx.IsSigned {
  265. ctx.SetCookie("redirect_to", "/"+url.QueryEscape(ctx.Req.RequestURI))
  266. ctx.Redirect("/user/login")
  267. return
  268. }
  269. ctx.Handle(404, ctx.Req.RequestURI, nil)
  270. return
  271. }
  272. }
  273. }