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.2 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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(setting.AppSubUrl + "/")
  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(setting.AppSubUrl + "/")
  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(setting.AppSubUrl + "/")
  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, repo.Id, 0)
  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, err = repo.RepoLink()
  146. if err != nil {
  147. ctx.Handle(500, "RepoLink", err)
  148. return
  149. }
  150. ctx.Data["RepoLink"] = ctx.Repo.RepoLink
  151. tags, err := ctx.Repo.GitRepo.GetTags()
  152. if err != nil {
  153. ctx.Handle(500, "GetTags", err)
  154. return
  155. }
  156. ctx.Data["Tags"] = tags
  157. ctx.Repo.Repository.NumTags = len(tags)
  158. // Non-fork repository will not return error in this method.
  159. if err = repo.GetForkRepo(); err != nil {
  160. ctx.Handle(500, "GetForkRepo", err)
  161. return
  162. }
  163. ctx.Data["Title"] = u.Name + "/" + repo.Name
  164. ctx.Data["Repository"] = repo
  165. ctx.Data["Owner"] = ctx.Repo.Repository.Owner
  166. ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
  167. ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner
  168. if setting.SshPort != 22 {
  169. ctx.Repo.CloneLink.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.Domain, setting.SshPort, u.LowerName, repo.LowerName)
  170. } else {
  171. ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.Domain, u.LowerName, repo.LowerName)
  172. }
  173. ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, u.LowerName, repo.LowerName)
  174. ctx.Data["CloneLink"] = ctx.Repo.CloneLink
  175. if ctx.Repo.Repository.IsGoget {
  176. ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", setting.AppUrl, u.LowerName, repo.LowerName)
  177. ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", setting.Domain, u.LowerName, repo.LowerName)
  178. }
  179. // when repo is bare, not valid branch
  180. if !ctx.Repo.Repository.IsBare && validBranch {
  181. detect:
  182. if len(refName) > 0 {
  183. if gitRepo.IsBranchExist(refName) {
  184. ctx.Repo.IsBranch = true
  185. ctx.Repo.BranchName = refName
  186. ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(refName)
  187. if err != nil {
  188. ctx.Handle(500, "RepoAssignment invalid branch", err)
  189. return
  190. }
  191. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  192. } else if gitRepo.IsTagExist(refName) {
  193. ctx.Repo.IsTag = true
  194. ctx.Repo.BranchName = refName
  195. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfTag(refName)
  196. if err != nil {
  197. ctx.Handle(500, "Fail to get tag commit", err)
  198. return
  199. }
  200. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  201. } else if len(refName) == 40 {
  202. ctx.Repo.IsCommit = true
  203. ctx.Repo.CommitId = refName
  204. ctx.Repo.BranchName = refName
  205. ctx.Repo.Commit, err = gitRepo.GetCommit(refName)
  206. if err != nil {
  207. ctx.Handle(404, "RepoAssignment invalid commit", nil)
  208. return
  209. }
  210. } else {
  211. ctx.Handle(404, "RepoAssignment invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
  212. return
  213. }
  214. } else {
  215. if len(refName) == 0 {
  216. if gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  217. refName = ctx.Repo.Repository.DefaultBranch
  218. } else {
  219. brs, err := gitRepo.GetBranches()
  220. if err != nil {
  221. ctx.Handle(500, "GetBranches", err)
  222. return
  223. }
  224. refName = brs[0]
  225. }
  226. }
  227. goto detect
  228. }
  229. ctx.Data["IsBranch"] = ctx.Repo.IsBranch
  230. ctx.Data["IsTag"] = ctx.Repo.IsTag
  231. ctx.Data["IsCommit"] = ctx.Repo.IsCommit
  232. ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
  233. if err != nil {
  234. ctx.Handle(500, "CommitsCount", err)
  235. return
  236. }
  237. ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
  238. }
  239. // repo is bare and display enable
  240. if ctx.Repo.Repository.IsBare {
  241. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  242. if displayBare {
  243. ctx.HTML(200, "repo/bare")
  244. }
  245. return
  246. }
  247. if ctx.IsSigned {
  248. ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.Id, repo.Id)
  249. ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.Id, repo.Id)
  250. }
  251. ctx.Data["TagName"] = ctx.Repo.TagName
  252. brs, err := ctx.Repo.GitRepo.GetBranches()
  253. if err != nil {
  254. ctx.Handle(500, "GetBranches", err)
  255. return
  256. }
  257. ctx.Data["Branches"] = brs
  258. ctx.Data["BrancheCount"] = len(brs)
  259. // If not branch selected, try default one.
  260. // If default branch doesn't exists, fall back to some other branch.
  261. if ctx.Repo.BranchName == "" {
  262. if ctx.Repo.Repository.DefaultBranch != "" && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  263. ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
  264. } else if len(brs) > 0 {
  265. ctx.Repo.BranchName = brs[0]
  266. }
  267. }
  268. ctx.Data["BranchName"] = ctx.Repo.BranchName
  269. ctx.Data["CommitId"] = ctx.Repo.CommitId
  270. }
  271. }
  272. func RequireTrueOwner() macaron.Handler {
  273. return func(ctx *Context) {
  274. if !ctx.Repo.IsTrueOwner && !ctx.Repo.IsAdmin {
  275. if !ctx.IsSigned {
  276. ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
  277. ctx.Redirect(setting.AppSubUrl + "/user/login")
  278. return
  279. }
  280. ctx.Handle(404, ctx.Req.RequestURI, nil)
  281. return
  282. }
  283. }
  284. }
  285. // GitHookService checks if repsitory Git hooks service has been enabled.
  286. func GitHookService() macaron.Handler {
  287. return func(ctx *Context) {
  288. if !setting.Service.EnableGitHooks {
  289. ctx.Handle(404, "GitHookService", nil)
  290. return
  291. }
  292. }
  293. }