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