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.8 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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/git-shell"
  11. "github.com/gogits/gogs/models"
  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. ctx.Data["Mirror"] = ctx.Repo.Mirror
  119. }
  120. ctx.Repo.Repository = repo
  121. ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
  122. gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
  123. if err != nil {
  124. ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
  125. return
  126. }
  127. ctx.Repo.GitRepo = gitRepo
  128. ctx.Repo.RepoLink = repo.RepoLink()
  129. ctx.Data["RepoLink"] = ctx.Repo.RepoLink
  130. ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
  131. tags, err := ctx.Repo.GitRepo.GetTags()
  132. if err != nil {
  133. ctx.Handle(500, "GetTags", err)
  134. return
  135. }
  136. ctx.Data["Tags"] = tags
  137. ctx.Repo.Repository.NumTags = len(tags)
  138. if repo.IsFork {
  139. RetrieveBaseRepo(ctx, repo)
  140. if ctx.Written() {
  141. return
  142. }
  143. }
  144. ctx.Data["Title"] = owner.Name + "/" + repo.Name
  145. ctx.Data["Repository"] = repo
  146. ctx.Data["Owner"] = ctx.Repo.Repository.Owner
  147. ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner()
  148. ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin()
  149. ctx.Data["IsRepositoryPusher"] = ctx.Repo.IsPusher()
  150. ctx.Data["CanPullRequest"] = ctx.Repo.IsAdmin() && repo.BaseRepo != nil && repo.BaseRepo.EnablePulls
  151. ctx.Data["DisableSSH"] = setting.DisableSSH
  152. ctx.Data["CloneLink"] = repo.CloneLink()
  153. ctx.Data["WikiCloneLink"] = repo.WikiCloneLink()
  154. if ctx.IsSigned {
  155. ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.Id, repo.ID)
  156. ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.Id, repo.ID)
  157. }
  158. // repo is bare and display enable
  159. if ctx.Repo.Repository.IsBare {
  160. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  161. // NOTE: to prevent templating error
  162. ctx.Data["BranchName"] = ""
  163. if displayBare {
  164. if !ctx.Repo.IsAdmin() {
  165. ctx.Flash.Info(ctx.Tr("repo.repo_is_empty"), true)
  166. }
  167. ctx.HTML(200, "repo/bare")
  168. }
  169. return
  170. }
  171. ctx.Data["TagName"] = ctx.Repo.TagName
  172. brs, err := ctx.Repo.GitRepo.GetBranches()
  173. if err != nil {
  174. ctx.Handle(500, "GetBranches", err)
  175. return
  176. }
  177. ctx.Data["Branches"] = brs
  178. ctx.Data["BrancheCount"] = len(brs)
  179. // If not branch selected, try default one.
  180. // If default branch doesn't exists, fall back to some other branch.
  181. if len(ctx.Repo.BranchName) == 0 {
  182. if len(ctx.Repo.Repository.DefaultBranch) > 0 && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  183. ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
  184. } else if len(brs) > 0 {
  185. ctx.Repo.BranchName = brs[0]
  186. }
  187. }
  188. ctx.Data["BranchName"] = ctx.Repo.BranchName
  189. ctx.Data["CommitID"] = ctx.Repo.CommitID
  190. if ctx.Query("go-get") == "1" {
  191. ctx.Data["GoGetImport"] = path.Join(setting.Domain, setting.AppSubUrl, owner.Name, repo.Name)
  192. prefix := path.Join(setting.AppUrl, owner.Name, repo.Name, "src", ctx.Repo.BranchName)
  193. ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
  194. ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
  195. }
  196. }
  197. }
  198. // RepoRef handles repository reference name including those contain `/`.
  199. func RepoRef() macaron.Handler {
  200. return func(ctx *Context) {
  201. // Empty repository does not have reference information.
  202. if ctx.Repo.Repository.IsBare {
  203. return
  204. }
  205. var (
  206. refName string
  207. err error
  208. )
  209. // For API calls.
  210. if ctx.Repo.GitRepo == nil {
  211. repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
  212. gitRepo, err := git.OpenRepository(repoPath)
  213. if err != nil {
  214. ctx.Handle(500, "RepoRef Invalid repo "+repoPath, err)
  215. return
  216. }
  217. ctx.Repo.GitRepo = gitRepo
  218. }
  219. // Get default branch.
  220. if len(ctx.Params("*")) == 0 {
  221. refName = ctx.Repo.Repository.DefaultBranch
  222. if !ctx.Repo.GitRepo.IsBranchExist(refName) {
  223. brs, err := ctx.Repo.GitRepo.GetBranches()
  224. if err != nil {
  225. ctx.Handle(500, "GetBranches", err)
  226. return
  227. }
  228. refName = brs[0]
  229. }
  230. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
  231. if err != nil {
  232. ctx.Handle(500, "GetBranchCommit", err)
  233. return
  234. }
  235. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  236. ctx.Repo.IsViewBranch = true
  237. } else {
  238. hasMatched := false
  239. parts := strings.Split(ctx.Params("*"), "/")
  240. for i, part := range parts {
  241. refName = strings.TrimPrefix(refName+"/"+part, "/")
  242. if ctx.Repo.GitRepo.IsBranchExist(refName) ||
  243. ctx.Repo.GitRepo.IsTagExist(refName) {
  244. if i < len(parts)-1 {
  245. ctx.Repo.TreeName = strings.Join(parts[i+1:], "/")
  246. }
  247. hasMatched = true
  248. break
  249. }
  250. }
  251. if !hasMatched && len(parts[0]) == 40 {
  252. refName = parts[0]
  253. ctx.Repo.TreeName = strings.Join(parts[1:], "/")
  254. }
  255. if ctx.Repo.GitRepo.IsBranchExist(refName) {
  256. ctx.Repo.IsViewBranch = true
  257. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
  258. if err != nil {
  259. ctx.Handle(500, "GetBranchCommit", err)
  260. return
  261. }
  262. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  263. } else if ctx.Repo.GitRepo.IsTagExist(refName) {
  264. ctx.Repo.IsViewTag = true
  265. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
  266. if err != nil {
  267. ctx.Handle(500, "GetTagCommit", err)
  268. return
  269. }
  270. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  271. } else if len(refName) == 40 {
  272. ctx.Repo.IsViewCommit = true
  273. ctx.Repo.CommitID = refName
  274. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
  275. if err != nil {
  276. ctx.Handle(404, "GetCommit", nil)
  277. return
  278. }
  279. } else {
  280. ctx.Handle(404, "RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
  281. return
  282. }
  283. }
  284. ctx.Repo.BranchName = refName
  285. ctx.Data["BranchName"] = ctx.Repo.BranchName
  286. ctx.Data["CommitID"] = ctx.Repo.CommitID
  287. ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch
  288. ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag
  289. ctx.Data["IsViewCommit"] = ctx.Repo.IsViewCommit
  290. ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
  291. if err != nil {
  292. ctx.Handle(500, "CommitsCount", err)
  293. return
  294. }
  295. ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
  296. }
  297. }
  298. func RequireRepoAdmin() macaron.Handler {
  299. return func(ctx *Context) {
  300. if !ctx.Repo.IsAdmin() {
  301. ctx.Handle(404, ctx.Req.RequestURI, nil)
  302. return
  303. }
  304. }
  305. }
  306. func RequireRepoPusher() macaron.Handler {
  307. return func(ctx *Context) {
  308. if !ctx.Repo.IsPusher() {
  309. ctx.Handle(404, ctx.Req.RequestURI, nil)
  310. return
  311. }
  312. }
  313. }
  314. // GitHookService checks if repository Git hooks service has been enabled.
  315. func GitHookService() macaron.Handler {
  316. return func(ctx *Context) {
  317. if !ctx.User.CanEditGitHook() {
  318. ctx.Handle(404, "GitHookService", nil)
  319. return
  320. }
  321. }
  322. }