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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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 context
  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. ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
  194. if ctx.Query("go-get") == "1" {
  195. ctx.Data["GoGetImport"] = path.Join(setting.Domain, setting.AppSubUrl, owner.Name, repo.Name)
  196. prefix := setting.AppUrl + path.Join(owner.Name, repo.Name, "src", ctx.Repo.BranchName)
  197. ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
  198. ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
  199. }
  200. }
  201. }
  202. // RepoRef handles repository reference name including those contain `/`.
  203. func RepoRef() macaron.Handler {
  204. return func(ctx *Context) {
  205. // Empty repository does not have reference information.
  206. if ctx.Repo.Repository.IsBare {
  207. return
  208. }
  209. var (
  210. refName string
  211. err error
  212. )
  213. // For API calls.
  214. if ctx.Repo.GitRepo == nil {
  215. repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
  216. gitRepo, err := git.OpenRepository(repoPath)
  217. if err != nil {
  218. ctx.Handle(500, "RepoRef Invalid repo "+repoPath, err)
  219. return
  220. }
  221. ctx.Repo.GitRepo = gitRepo
  222. }
  223. // Get default branch.
  224. if len(ctx.Params("*")) == 0 {
  225. refName = ctx.Repo.Repository.DefaultBranch
  226. if !ctx.Repo.GitRepo.IsBranchExist(refName) {
  227. brs, err := ctx.Repo.GitRepo.GetBranches()
  228. if err != nil {
  229. ctx.Handle(500, "GetBranches", err)
  230. return
  231. }
  232. refName = brs[0]
  233. }
  234. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
  235. if err != nil {
  236. ctx.Handle(500, "GetBranchCommit", err)
  237. return
  238. }
  239. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  240. ctx.Repo.IsViewBranch = true
  241. } else {
  242. hasMatched := false
  243. parts := strings.Split(ctx.Params("*"), "/")
  244. for i, part := range parts {
  245. refName = strings.TrimPrefix(refName+"/"+part, "/")
  246. if ctx.Repo.GitRepo.IsBranchExist(refName) ||
  247. ctx.Repo.GitRepo.IsTagExist(refName) {
  248. if i < len(parts)-1 {
  249. ctx.Repo.TreeName = strings.Join(parts[i+1:], "/")
  250. }
  251. hasMatched = true
  252. break
  253. }
  254. }
  255. if !hasMatched && len(parts[0]) == 40 {
  256. refName = parts[0]
  257. ctx.Repo.TreeName = strings.Join(parts[1:], "/")
  258. }
  259. if ctx.Repo.GitRepo.IsBranchExist(refName) {
  260. ctx.Repo.IsViewBranch = true
  261. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
  262. if err != nil {
  263. ctx.Handle(500, "GetBranchCommit", err)
  264. return
  265. }
  266. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  267. } else if ctx.Repo.GitRepo.IsTagExist(refName) {
  268. ctx.Repo.IsViewTag = true
  269. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
  270. if err != nil {
  271. ctx.Handle(500, "GetTagCommit", err)
  272. return
  273. }
  274. ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
  275. } else if len(refName) == 40 {
  276. ctx.Repo.IsViewCommit = true
  277. ctx.Repo.CommitID = refName
  278. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
  279. if err != nil {
  280. ctx.Handle(404, "GetCommit", nil)
  281. return
  282. }
  283. } else {
  284. ctx.Handle(404, "RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
  285. return
  286. }
  287. }
  288. ctx.Repo.BranchName = refName
  289. ctx.Data["BranchName"] = ctx.Repo.BranchName
  290. ctx.Data["CommitID"] = ctx.Repo.CommitID
  291. ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch
  292. ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag
  293. ctx.Data["IsViewCommit"] = ctx.Repo.IsViewCommit
  294. ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
  295. if err != nil {
  296. ctx.Handle(500, "CommitsCount", err)
  297. return
  298. }
  299. ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
  300. }
  301. }
  302. func RequireRepoAdmin() macaron.Handler {
  303. return func(ctx *Context) {
  304. if !ctx.IsSigned || (!ctx.Repo.IsAdmin() && !ctx.User.IsAdmin) {
  305. ctx.Handle(404, ctx.Req.RequestURI, nil)
  306. return
  307. }
  308. }
  309. }
  310. func RequireRepoWriter() macaron.Handler {
  311. return func(ctx *Context) {
  312. if !ctx.IsSigned || (!ctx.Repo.IsWriter() && !ctx.User.IsAdmin) {
  313. ctx.Handle(404, ctx.Req.RequestURI, nil)
  314. return
  315. }
  316. }
  317. }
  318. // GitHookService checks if repository Git hooks service has been enabled.
  319. func GitHookService() macaron.Handler {
  320. return func(ctx *Context) {
  321. if !ctx.User.CanEditGitHook() {
  322. ctx.Handle(404, "GitHookService", nil)
  323. return
  324. }
  325. }
  326. }