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.7 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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. "fmt"
  7. "path"
  8. "strings"
  9. "gopkg.in/macaron.v1"
  10. "github.com/gogits/gogs/models"
  11. "github.com/gogits/gogs/modules/git"
  12. "github.com/gogits/gogs/modules/log"
  13. "github.com/gogits/gogs/modules/setting"
  14. )
  15. func RetrieveBaseRepo(ctx *Context, repo *models.Repository) {
  16. // Non-fork repository will not return error in this method.
  17. if err := repo.GetBaseRepo(); err != nil {
  18. if models.IsErrRepoNotExist(err) {
  19. repo.IsFork = false
  20. repo.ForkID = 0
  21. return
  22. }
  23. ctx.Handle(500, "GetBaseRepo", err)
  24. return
  25. } else if err = repo.BaseRepo.GetOwner(); err != nil {
  26. ctx.Handle(500, "BaseRepo.GetOwner", err)
  27. return
  28. }
  29. bsaeRepo := repo.BaseRepo
  30. baseGitRepo, err := git.OpenRepository(models.RepoPath(bsaeRepo.Owner.Name, bsaeRepo.Name))
  31. if err != nil {
  32. ctx.Handle(500, "OpenRepository", err)
  33. return
  34. }
  35. if len(bsaeRepo.DefaultBranch) > 0 && baseGitRepo.IsBranchExist(bsaeRepo.DefaultBranch) {
  36. ctx.Data["BaseDefaultBranch"] = bsaeRepo.DefaultBranch
  37. } else {
  38. baseBranches, err := baseGitRepo.GetBranches()
  39. if err != nil {
  40. ctx.Handle(500, "GetBranches", err)
  41. return
  42. }
  43. if len(baseBranches) > 0 {
  44. ctx.Data["BaseDefaultBranch"] = baseBranches[0]
  45. }
  46. }
  47. }
  48. func RepoAssignment(args ...bool) macaron.Handler {
  49. return func(ctx *Context) {
  50. var (
  51. displayBare bool // To display bare page if it is a bare repo.
  52. )
  53. if len(args) >= 1 {
  54. displayBare = args[0]
  55. }
  56. var (
  57. owner *models.User
  58. err error
  59. )
  60. userName := ctx.Params(":username")
  61. repoName := ctx.Params(":reponame")
  62. refName := ctx.Params(":branchname")
  63. if len(refName) == 0 {
  64. refName = ctx.Params(":path")
  65. }
  66. // Check if the user is the same as the repository owner
  67. if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) {
  68. owner = ctx.User
  69. } else {
  70. owner, err = models.GetUserByName(userName)
  71. if err != nil {
  72. if models.IsErrUserNotExist(err) {
  73. ctx.Handle(404, "GetUserByName", err)
  74. } else {
  75. ctx.Handle(500, "GetUserByName", err)
  76. }
  77. return
  78. }
  79. }
  80. ctx.Repo.Owner = owner
  81. // Get repository.
  82. repo, err := models.GetRepositoryByName(owner.Id, repoName)
  83. if err != nil {
  84. if models.IsErrRepoNotExist(err) {
  85. ctx.Handle(404, "GetRepositoryByName", err)
  86. } else {
  87. ctx.Handle(500, "GetRepositoryByName", err)
  88. }
  89. return
  90. } else if err = repo.GetOwner(); err != nil {
  91. ctx.Handle(500, "GetOwner", err)
  92. return
  93. }
  94. // Admin has super access.
  95. if ctx.IsSigned && ctx.User.IsAdmin {
  96. ctx.Repo.AccessMode = models.ACCESS_MODE_OWNER
  97. } else {
  98. mode, err := models.AccessLevel(ctx.User, repo)
  99. if err != nil {
  100. ctx.Handle(500, "AccessLevel", err)
  101. return
  102. }
  103. ctx.Repo.AccessMode = mode
  104. }
  105. // Check access.
  106. if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
  107. ctx.Handle(404, "no access right", err)
  108. return
  109. }
  110. ctx.Data["HasAccess"] = true
  111. if repo.IsMirror {
  112. ctx.Repo.Mirror, err = models.GetMirror(repo.ID)
  113. if err != nil {
  114. ctx.Handle(500, "GetMirror", err)
  115. return
  116. }
  117. ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval
  118. }
  119. ctx.Repo.Repository = repo
  120. ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
  121. gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
  122. if err != nil {
  123. ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
  124. return
  125. }
  126. ctx.Repo.GitRepo = gitRepo
  127. ctx.Repo.RepoLink = repo.RepoLink()
  128. ctx.Data["RepoLink"] = ctx.Repo.RepoLink
  129. ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
  130. tags, err := ctx.Repo.GitRepo.GetTags()
  131. if err != nil {
  132. ctx.Handle(500, "GetTags", err)
  133. return
  134. }
  135. ctx.Data["Tags"] = tags
  136. ctx.Repo.Repository.NumTags = len(tags)
  137. if repo.IsFork {
  138. RetrieveBaseRepo(ctx, repo)
  139. if ctx.Written() {
  140. return
  141. }
  142. }
  143. ctx.Data["Title"] = owner.Name + "/" + repo.Name
  144. ctx.Data["Repository"] = repo
  145. ctx.Data["Owner"] = ctx.Repo.Repository.Owner
  146. ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner()
  147. ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin()
  148. ctx.Data["IsRepositoryPusher"] = ctx.Repo.IsPusher()
  149. ctx.Data["CanPullRequest"] = ctx.Repo.IsAdmin() && repo.BaseRepo != nil && repo.BaseRepo.EnablePulls
  150. ctx.Data["DisableSSH"] = setting.DisableSSH
  151. ctx.Data["CloneLink"] = repo.CloneLink()
  152. ctx.Data["WikiCloneLink"] = repo.WikiCloneLink()
  153. if ctx.IsSigned {
  154. ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.Id, repo.ID)
  155. ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.Id, repo.ID)
  156. }
  157. // repo is bare and display enable
  158. if ctx.Repo.Repository.IsBare {
  159. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  160. // NOTE: to prevent templating error
  161. ctx.Data["BranchName"] = ""
  162. if displayBare {
  163. if !ctx.Repo.IsAdmin() {
  164. ctx.Flash.Info(ctx.Tr("repo.repo_is_empty"), true)
  165. }
  166. ctx.HTML(200, "repo/bare")
  167. }
  168. return
  169. }
  170. ctx.Data["TagName"] = ctx.Repo.TagName
  171. brs, err := ctx.Repo.GitRepo.GetBranches()
  172. if err != nil {
  173. ctx.Handle(500, "GetBranches", err)
  174. return
  175. }
  176. ctx.Data["Branches"] = brs
  177. ctx.Data["BrancheCount"] = len(brs)
  178. // If not branch selected, try default one.
  179. // If default branch doesn't exists, fall back to some other branch.
  180. if len(ctx.Repo.BranchName) == 0 {
  181. if len(ctx.Repo.Repository.DefaultBranch) > 0 && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  182. ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
  183. } else if len(brs) > 0 {
  184. ctx.Repo.BranchName = brs[0]
  185. }
  186. }
  187. ctx.Data["BranchName"] = ctx.Repo.BranchName
  188. ctx.Data["CommitID"] = ctx.Repo.CommitID
  189. if ctx.Query("go-get") == "1" {
  190. ctx.Data["GoGetImport"] = path.Join(setting.Domain, setting.AppSubUrl, owner.Name, repo.Name)
  191. prefix := path.Join(setting.AppUrl, owner.Name, repo.Name, "src", ctx.Repo.BranchName)
  192. ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
  193. ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
  194. }
  195. }
  196. }
  197. // RepoRef handles repository reference name including those contain `/`.
  198. func RepoRef() macaron.Handler {
  199. return func(ctx *Context) {
  200. // Empty repository does not have reference information.
  201. if ctx.Repo.Repository.IsBare {
  202. return
  203. }
  204. var (
  205. refName string
  206. err error
  207. )
  208. // For API calls.
  209. if ctx.Repo.GitRepo == nil {
  210. repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
  211. gitRepo, err := git.OpenRepository(repoPath)
  212. if err != nil {
  213. ctx.Handle(500, "RepoRef Invalid repo "+repoPath, err)
  214. return
  215. }
  216. ctx.Repo.GitRepo = gitRepo
  217. }
  218. // Get default branch.
  219. if len(ctx.Params("*")) == 0 {
  220. refName = ctx.Repo.Repository.DefaultBranch
  221. if !ctx.Repo.GitRepo.IsBranchExist(refName) {
  222. brs, err := ctx.Repo.GitRepo.GetBranches()
  223. if err != nil {
  224. ctx.Handle(500, "GetBranches", err)
  225. return
  226. }
  227. refName = brs[0]
  228. }
  229. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName)
  230. if err != nil {
  231. ctx.Handle(500, "GetCommitOfBranch", err)
  232. return
  233. }
  234. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  235. ctx.Repo.IsBranch = true
  236. } else {
  237. hasMatched := false
  238. parts := strings.Split(ctx.Params("*"), "/")
  239. for i, part := range parts {
  240. refName = strings.TrimPrefix(refName+"/"+part, "/")
  241. if ctx.Repo.GitRepo.IsBranchExist(refName) ||
  242. ctx.Repo.GitRepo.IsTagExist(refName) {
  243. if i < len(parts)-1 {
  244. ctx.Repo.TreeName = strings.Join(parts[i+1:], "/")
  245. }
  246. hasMatched = true
  247. break
  248. }
  249. }
  250. if !hasMatched && len(parts[0]) == 40 {
  251. refName = parts[0]
  252. ctx.Repo.TreeName = strings.Join(parts[1:], "/")
  253. }
  254. if ctx.Repo.GitRepo.IsBranchExist(refName) {
  255. ctx.Repo.IsBranch = true
  256. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName)
  257. if err != nil {
  258. ctx.Handle(500, "GetCommitOfBranch", err)
  259. return
  260. }
  261. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  262. } else if ctx.Repo.GitRepo.IsTagExist(refName) {
  263. ctx.Repo.IsTag = true
  264. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfTag(refName)
  265. if err != nil {
  266. ctx.Handle(500, "GetCommitOfTag", err)
  267. return
  268. }
  269. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  270. } else if len(refName) == 40 {
  271. ctx.Repo.IsCommit = true
  272. ctx.Repo.CommitID = refName
  273. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
  274. if err != nil {
  275. ctx.Handle(404, "GetCommit", nil)
  276. return
  277. }
  278. } else {
  279. ctx.Handle(404, "RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
  280. return
  281. }
  282. }
  283. ctx.Repo.BranchName = refName
  284. ctx.Data["BranchName"] = ctx.Repo.BranchName
  285. ctx.Data["CommitID"] = ctx.Repo.CommitID
  286. ctx.Data["IsBranch"] = ctx.Repo.IsBranch
  287. ctx.Data["IsTag"] = ctx.Repo.IsTag
  288. ctx.Data["IsCommit"] = ctx.Repo.IsCommit
  289. ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
  290. if err != nil {
  291. ctx.Handle(500, "CommitsCount", err)
  292. return
  293. }
  294. ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
  295. }
  296. }
  297. func RequireRepoAdmin() macaron.Handler {
  298. return func(ctx *Context) {
  299. if !ctx.Repo.IsAdmin() {
  300. ctx.Handle(404, ctx.Req.RequestURI, nil)
  301. return
  302. }
  303. }
  304. }
  305. func RequireRepoPusher() macaron.Handler {
  306. return func(ctx *Context) {
  307. if !ctx.Repo.IsPusher() {
  308. ctx.Handle(404, ctx.Req.RequestURI, nil)
  309. return
  310. }
  311. }
  312. }
  313. // GitHookService checks if repository Git hooks service has been enabled.
  314. func GitHookService() macaron.Handler {
  315. return func(ctx *Context) {
  316. if !ctx.User.CanEditGitHook() {
  317. ctx.Handle(404, "GitHookService", nil)
  318. return
  319. }
  320. }
  321. }